Visitar URL original
Optional Unicode 3.2.0 but enabled by default by joshuamegnauth54 · Pull Request #9011 · RustPython/RustPython · GitHub
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Optional Unicode 3.2.0 but enabled by default
Useful for smaller builds, like WebAssembly. The UCD 3.2.0 path is only
directly used in a handful of places in Python.

Assisted-by: GPT-5.6-Luna
  • Loading branch information
joshuamegnauth54 committed Oct 9, 2026
commit 4b3e66064d45586822ac733def65c8794305da32
6 changes: 3 additions & 3 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ concurrency:
cancel-in-progress: true

env:
CARGO_ARGS: --no-default-features --features stdlib,importlib,stdio,encodings,sqlite,ssl-rustls-aws-lc,host_env,doc
CARGO_ARGS_NO_SSL: --no-default-features --features stdlib,importlib,stdio,encodings,sqlite,host_env,doc
CARGO_ARGS: --no-default-features --features stdlib,importlib,stdio,encodings,sqlite,ssl-rustls-aws-lc,host_env,doc,ucd_3_2_0
CARGO_ARGS_NO_SSL: --no-default-features --features stdlib,importlib,stdio,encodings,sqlite,host_env,doc,ucd_3_2_0
CARGO_ARGS_MOST_FEATS: --features capi,encodings,jit,sqlite,threading
# Crates excluded from workspace builds:
# - rustpython_wasm: requires wasm target
Expand Down Expand Up @@ -1072,7 +1072,7 @@ jobs:

- name: build rustpython
if: env.RUN_WASM_WASI == 'true'
run: cargo build --locked --profile wasm-release --target wasm32-wasip1 --no-default-features --features freeze-stdlib,stdlib,stdio,importlib,host_env,doc --verbose
run: cargo build --locked --profile wasm-release --target wasm32-wasip1 --no-default-features --features freeze-stdlib,stdlib,stdio,importlib,host_env,doc,ucd_3_2_0 --verbose
- name: run snippets
if: env.RUN_WASM_WASI == 'true'
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/cron-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ on:
- .github/workflows/cron-ci.yaml

env:
CARGO_ARGS: --no-default-features --features stdlib,importlib,stdio,encodings,ssl-rustls-aws-lc,jit,host_env,doc
CARGO_ARGS: --no-default-features --features stdlib,importlib,stdio,encodings,ssl-rustls-aws-lc,jit,host_env,doc,ucd_3_2_0

jobs:
# codecov collects code coverage data from the rust tests, python snippets and python test suite.
Expand Down Expand Up @@ -42,7 +42,7 @@ jobs:
- run: sudo apt-get update && sudo apt-get -y install lcov

- name: Run cargo-llvm-cov with Rust tests.
run: cargo llvm-cov --no-report --workspace --exclude rustpython_wasm --exclude rustpython-venvlauncher --exclude rustpython-capi --verbose --no-default-features --features stdlib,importlib,stdio,encodings,ssl-rustls-aws-lc,jit,host_env,doc
run: cargo llvm-cov --no-report --workspace --exclude rustpython_wasm --exclude rustpython-venvlauncher --exclude rustpython-capi --verbose --no-default-features --features stdlib,importlib,stdio,encodings,ssl-rustls-aws-lc,jit,host_env,doc,ucd_3_2_0

- name: Run cargo-llvm-cov with Python snippets.
run: python scripts/cargo-llvm-cov.py
Expand Down
7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ license.workspace = true

[features]
capi = ["dep:rustpython-capi", "threading"]
default = ["threading", "stdlib", "stdio", "importlib", "ssl-rustls-aws-lc", "host_env", "mimalloc", "doc"]
default = ["threading", "stdlib", "stdio", "importlib", "ssl-rustls-aws-lc", "host_env", "mimalloc", "doc", "ucd_3_2_0"]
doc = ["rustpython-vm/doc", "rustpython-stdlib?/doc"]
mimalloc = ["dep:mimalloc"]
host_env = ["rustpython-vm/host_env", "rustpython-stdlib?/host_env"]
Expand All @@ -32,6 +32,7 @@ ssl-rustls-aws-lc-fips = ["ssl-rustls-aws-lc", "rustls/fips"]
ssl-openssl = ["ssl", "rustpython-stdlib/ssl-openssl"]
ssl-openssl-vendor = ["ssl-openssl", "rustpython-stdlib/ssl-openssl-vendor"]
tkinter = ["rustpython-stdlib/tkinter"]
ucd_3_2_0 = ["rustpython-stdlib?/ucd_3_2_0", "rustpython-capi?/ucd_3_2_0"]

[build-dependencies]
winresource = "0.1"
Expand Down Expand Up @@ -169,7 +170,7 @@ repository = "https://github.com/RustPython/RustPython"
license = "MIT"

[workspace.dependencies]
rustpython-capi = { path = "crates/capi", version = "0.6.1" }
rustpython-capi = { path = "crates/capi", version = "0.6.1", default-features = false }
rustpython-compiler-core = { path = "crates/compiler-core", version = "0.6.1" }
rustpython-compiler = { path = "crates/compiler", version = "0.6.1" }
rustpython-codegen = { path = "crates/codegen", version = "0.6.1" }
Expand All @@ -183,7 +184,7 @@ rustpython-vm = { path = "crates/vm", default-features = false, version = "0.6.1
rustpython-pylib = { path = "crates/pylib", version = "0.6.1" }
rustpython-stdlib = { path = "crates/stdlib", default-features = false, version = "0.6.1" }
rustpython-sre_engine = { path = "crates/sre_engine", version = "0.6.1" }
rustpython-unicode = { path = "crates/unicode", version = "0.6.1" }
rustpython-unicode = { path = "crates/unicode", default-features = false, version = "0.6.1" }
rustpython-wtf8 = { path = "crates/wtf8", version = "0.6.1" }
rustpython-doc = { path = "crates/doc", version = "0.6.1" }

Expand Down
4 changes: 4 additions & 0 deletions crates/capi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ license.workspace = true
[lib]
crate-type = ["cdylib", "rlib"]

[features]
default = ["ucd_3_2_0"]
ucd_3_2_0 = ["rustpython-stdlib/ucd_3_2_0"]

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.

I do not think the capi should have any features like this. If a user wants to change rustpython-stdlib/ucd_3_2_0 they could just specify this dependency directly.

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.

oh, good point. thanks!

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.

Fair point. Reverted and force pushed.


[dependencies]
bitflags = { workspace = true }
itertools = { workspace = true }
Expand Down
18 changes: 13 additions & 5 deletions crates/common/src/lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@ use lock_api::{

cfg_select! {
feature = "threading" => {
pub use core::cell::LazyCell;
pub use detaching::{BlockingWaitHook, set_blocking_wait_hook, set_world_stopped};
pub use parking_lot::{RawMutex, RawRwLock, RawThreadId};
pub use std::sync::OnceLock as OnceCell;
pub use core::cell::LazyCell;
}
_ => {
mod cell_lock;
pub use cell_lock::{RawCellMutex as RawMutex, RawCellRwLock as RawRwLock, SingleThreadId as RawThreadId};
pub use cell_lock::{
RawCellMutex as RawMutex, RawCellRwLock as RawRwLock, SingleThreadId as RawThreadId,
};

pub use core::cell::{LazyCell, OnceCell};
}
Expand All @@ -37,13 +39,19 @@ cfg_select! {
unsafe impl<T, F> Sync for LazyLock<T, F> {}

impl<T, F: FnOnce() -> T> LazyLock<T, F> {
pub const fn new(f: F) -> Self { Self(core::cell::LazyCell::new(f)) }
pub fn force(this: &Self) -> &T { core::cell::LazyCell::force(&this.0) }
pub const fn new(f: F) -> Self {
Self(core::cell::LazyCell::new(f))
}
pub fn force(this: &Self) -> &T {
core::cell::LazyCell::force(&this.0)
}
}

impl<T, F: FnOnce() -> T> core::ops::Deref for LazyLock<T, F> {
type Target = T;
fn deref(&self) -> &T { &self.0 }
fn deref(&self) -> &T {
&self.0
}
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion crates/stdlib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
default = ["compiler", "host_env", "doc"]
default = ["compiler", "host_env", "doc", "ucd_3_2_0"]
ucd_3_2_0 = ["rustpython-unicode/ucd_3_2_0"]
doc = ["rustpython-vm/doc"]
host_env = ["rustpython-vm/host_env"]
compiler = ["rustpython-vm/compiler"]
Expand Down Expand Up @@ -73,7 +74,7 @@

# tkinter
tk-sys = { workspace = true, optional = true }
tcl-sys = { workspace = true, optional = true }

Check warning on line 77 in crates/stdlib/Cargo.toml

View workflow job for this annotation

GitHub Actions / cargo shear

shear/unused_optional_dependency

unused optional dependency `tcl-sys`
widestring = { workspace = true, optional = true }

# uuid
Expand Down
2 changes: 1 addition & 1 deletion crates/stdlib/src/_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ mod _queue {
use parking_lot::{Condvar, Mutex, MutexGuard};

type Buf = Mutex<BufInner>;
},
}
_ => {
use crate::common::lock::PyMutex;

Expand Down
14 changes: 6 additions & 8 deletions crates/stdlib/src/faulthandler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -679,10 +679,9 @@ mod decl {
// frames are still alive because the target thread
// is executing (inside a blocking call).
for (tid, slot) in &thread_frame_slots {
let iframe_ptr = slot
.top_iframe
.load(core::sync::atomic::Ordering::Relaxed)
as *const rustpython_vm::frame::InterpreterFrame;
let iframe_ptr =
slot.top_iframe.load(core::sync::atomic::Ordering::Relaxed)
as *const rustpython_vm::frame::InterpreterFrame;
write_thread_id(fd, *tid, false);
if iframe_ptr.is_null() {
puts(fd, " <no Python frame>\n");
Expand All @@ -703,10 +702,9 @@ mod decl {
}
all(not(unix), feature = "threading") => {
for (tid, slot) in &thread_frame_slots {
let iframe_ptr = slot
.top_iframe
.load(core::sync::atomic::Ordering::Relaxed)
as *const rustpython_vm::frame::InterpreterFrame;
let iframe_ptr =
slot.top_iframe.load(core::sync::atomic::Ordering::Relaxed)
as *const rustpython_vm::frame::InterpreterFrame;
write_thread_id(fd, *tid, false);
if iframe_ptr.is_null() {
puts(fd, " <no Python frame>\n");
Expand Down
20 changes: 9 additions & 11 deletions crates/stdlib/src/openssl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1338,7 +1338,8 @@ mod _ssl {
cfg_select! {
ossl110 => {
let ctx = zelf.builder();
let result = unsafe { sys::SSL_CTX_set_num_tickets(ctx.as_ptr(), value as usize) };
let result =
unsafe { sys::SSL_CTX_set_num_tickets(ctx.as_ptr(), value as usize) };
if result != 1 {
return Err(vm.new_value_error("failed to set num tickets."));
}
Expand All @@ -1360,11 +1361,10 @@ mod _ssl {
.load_verify_locations(Some(cert_file.as_path()), Some(cert_dir.as_path()))
.map_err(|e| convert_openssl_error(vm, e))
}
_ => {
zelf.builder()
.set_default_verify_paths()
.map_err(|e| convert_openssl_error(vm, e))
}
_ => zelf
.builder()
.set_default_verify_paths()
.map_err(|e| convert_openssl_error(vm, e)),
}
}

Expand Down Expand Up @@ -2828,11 +2828,9 @@ mod _ssl {
Ok(())
}
}
_ => {
Err(vm.new_not_implemented_error(
"Post-handshake auth is not supported by your OpenSSL version.",
))
}
_ => Err(vm.new_not_implemented_error(
"Post-handshake auth is not supported by your OpenSSL version.",
)),
}
}

Expand Down
4 changes: 1 addition & 3 deletions crates/stdlib/src/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ mod resource {

#[cfg_attr(target_os = "android", expect(deprecated))]
const RLIM_NLIMITS: i32 = cfg_select! {
target_os = "android" => {
host_resource::RLIM_NLIMITS
}
target_os = "android" => host_resource::RLIM_NLIMITS,
_ => {
// This constant isn't abi-stable across os versions, so we just
// pick a high number so we don't get false positive ValueErrors and just bubble up the
Expand Down
5 changes: 3 additions & 2 deletions crates/stdlib/src/unicodedata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl<'a> TryFromBorrowedObject<'a> for NormalizeFormArg {
mod unicodedata {
use super::{NormalizeFormArg, unicode_core};
use crate::vm::{
Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
Py, PyObjectRef, PyPayload, PyResult, VirtualMachine,
builtins::{PyModule, PyStr, PyStrRef},
function::OptionalArg,
};
Expand Down Expand Up @@ -244,8 +244,9 @@ mod unicodedata {
}
}

#[cfg(feature = "ucd_3_2_0")]
#[pyattr]
fn ucd_3_2_0(vm: &VirtualMachine) -> PyRef<Ucd> {
fn ucd_3_2_0(vm: &VirtualMachine) -> crate::vm::PyRef<Ucd> {
Ucd::new(false).into_ref(&vm.ctx)
}

Expand Down
4 changes: 4 additions & 0 deletions crates/unicode/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ repository = { workspace = true }
license = { workspace = true }
rust-version = { workspace = true }

[features]
default = ["ucd_3_2_0"]
ucd_3_2_0 = []

[dependencies]
rustpython-wtf8 = { workspace = true }

Expand Down
4 changes: 4 additions & 0 deletions crates/unicode/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -678,10 +678,14 @@ fn generate_numeric_value(
"(u32, u32, f64)",
&mut values_latest,
);
#[cfg(feature = "ucd_3_2_0")]
let mut ucd32_diffs: Vec<_> = ucd32_diffs
.into_iter()
.map(|((start, end), value)| (start, end, value))
.collect();
#[cfg(not(feature = "ucd_3_2_0"))]
let mut ucd32_diffs = Vec::new();

write_slice_debug(
&mut writer,
"NUMERIC_VALUES_DIFF",
Expand Down
32 changes: 30 additions & 2 deletions crates/unicode/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,46 @@ use icu_properties::props::{
};
use rustpython_wtf8::CodePoint;

// Latest Unicode
include!(concat!(env!("OUT_DIR"), "/generated/algo_names.rs"));
include!(concat!(env!("OUT_DIR"), "/generated/name_lookups.rs"));
include!(concat!(env!("OUT_DIR"), "/generated/decomp.rs"));
include!(concat!(env!("OUT_DIR"), "/generated/numeric_value_3_2.rs"));

// Unicode 3.2.0
#[cfg(feature = "ucd_3_2_0")]
include!(concat!(env!("OUT_DIR"), "/generated/bidi_class_3_2.rs"));
#[cfg(feature = "ucd_3_2_0")]
include!(concat!(env!("OUT_DIR"), "/generated/binary_props_3_2.rs"));
#[cfg(feature = "ucd_3_2_0")]
include!(concat!(
env!("OUT_DIR"),
"/generated/combining_class_3_2.rs"
));
include!(concat!(env!("OUT_DIR"), "/generated/decomp.rs"));
#[cfg(feature = "ucd_3_2_0")]
include!(concat!(env!("OUT_DIR"), "/generated/eaw_3_2.rs"));
#[cfg(feature = "ucd_3_2_0")]
include!(concat!(env!("OUT_DIR"), "/generated/gen_cat_3_2.rs"));
#[cfg(feature = "ucd_3_2_0")]
include!(concat!(env!("OUT_DIR"), "/generated/membership_3_2.rs"));
include!(concat!(env!("OUT_DIR"), "/generated/numeric_value_3_2.rs"));
#[cfg(feature = "ucd_3_2_0")]
include!(concat!(env!("OUT_DIR"), "/generated/num_type_3_2.rs"));

#[cfg(not(feature = "ucd_3_2_0"))]
const BIDI_CLASS_DIFF: &[(u32, u32, BidiClass)] = &[];
#[cfg(not(feature = "ucd_3_2_0"))]
const BIDI_MIRRORED: &[(u32, u32)] = &[];
#[cfg(not(feature = "ucd_3_2_0"))]
const COMBINING_CLASS: &[(u32, u32, CanonicalCombiningClass)] = &[];
#[cfg(not(feature = "ucd_3_2_0"))]
const EAST_ASIAN_WIDTH: &[(u32, u32, EastAsianWidth)] = &[];
#[cfg(not(feature = "ucd_3_2_0"))]
const GENERAL_CATEGORY: &[(u32, u32, GeneralCategory)] = &[];
#[cfg(not(feature = "ucd_3_2_0"))]
const MEMBERSHIP_3_2: &[(u32, u32)] = &[];
Comment thread
coderabbitai[bot] marked this conversation as resolved.
#[cfg(not(feature = "ucd_3_2_0"))]
const NUMERIC_TYPE_DIFF: &[(u32, u32, NumericType)] = &[];

#[derive(Clone, Copy)]
enum DecompositionType {
Compat,
Expand Down Expand Up @@ -511,12 +536,14 @@ mod tests {
}

#[test]
#[cfg(feature = "ucd_3_2_0")]
fn ucd_3_2_0_view_differs_from_modern() {
let legacy = Ucd::new(false);
assert_eq!(legacy.unidata_version(), "3.2.0");
}

#[test]
#[cfg(feature = "ucd_3_2_0")]
fn name_aliases_resolve_and_do_not_replace_the_official_name() {
assert_eq!(
lookup_character("LATIN CAPITAL LETTER GHA"),
Expand All @@ -534,6 +561,7 @@ mod tests {
}

#[test]
#[cfg(feature = "ucd_3_2_0")]
fn named_sequences_resolve_only_on_the_modern_view() {
assert_eq!(
lookup_name("LATIN SMALL LETTER R WITH TILDE"),
Expand Down
16 changes: 9 additions & 7 deletions crates/vm/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,14 +162,16 @@ fn get_version(cpy_version: &str) -> (String, String) {
// Windows: include MSC v. for compatibility with ctypes.util.find_library
// MSC v.1929 = VS 2019, version 14+ makes find_msvcrt() return None
let msc_info = cfg_select! {
windows => {{
// Include both RustPython identifier and MSC v. for compatibility
if cfg!(target_pointer_width = "64") {
" MSC v.1929 64 bit (AMD64)"
} else {
" MSC v.1929 32 bit (Intel)"
windows => {
{
// Include both RustPython identifier and MSC v. for compatibility
if cfg!(target_pointer_width = "64") {
" MSC v.1929 64 bit (AMD64)"
} else {
" MSC v.1929 32 bit (Intel)"
}
}
}},
}
_ => "",
};

Expand Down
2 changes: 1 addition & 1 deletion crates/vm/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ cfg_select! {
_ => {
pub use ruff_python_parser as parser;

pub use rustpython_compiler_core::Mode;
pub use rustpython_compiler_core as core;
pub use rustpython_compiler_core::Mode;
}
}

Expand Down
4 changes: 3 additions & 1 deletion crates/vm/src/exceptions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2726,7 +2726,9 @@ pub(super) mod types {
.filter(|f| !vm.is_none(f));

let winerror: Option<PyObjectRef> = cfg_select! {
windows => obj.get_attr("winerror", vm).ok().filter(|w| !vm.is_none(w)),
windows => {
obj.get_attr("winerror", vm).ok().filter(|w| !vm.is_none(w))
}
_ => None,
};

Expand Down
Loading
Loading