From 24f5442a7c65e1d49c93f67fa72f0a858062dc58 Mon Sep 17 00:00:00 2001 From: Noa Date: Sun, 30 Mar 2025 19:52:15 -0500 Subject: [PATCH] Make FromArgs default field take an expression, not a string literal --- Cargo.lock | 1 + derive-impl/src/from_args.rs | 4 ++-- derive/Cargo.toml | 1 + stdlib/src/binascii.rs | 14 +++++++------- stdlib/src/faulthandler.rs | 6 +++--- stdlib/src/hashlib.rs | 8 ++++---- stdlib/src/mmap.rs | 8 ++++---- stdlib/src/pystruct.rs | 2 +- stdlib/src/select.rs | 6 +++--- stdlib/src/socket.rs | 8 ++++---- stdlib/src/sqlite.rs | 20 ++++++++++---------- stdlib/src/ssl.rs | 2 +- stdlib/src/zlib.rs | 20 ++++++++++---------- vm/src/anystr.rs | 6 +++--- vm/src/builtins/int.rs | 6 +++--- vm/src/builtins/list.rs | 2 +- vm/src/stdlib/builtins.rs | 2 +- vm/src/stdlib/codecs.rs | 2 +- vm/src/stdlib/io.rs | 6 +++--- vm/src/stdlib/os.rs | 4 ++-- vm/src/stdlib/posix.rs | 2 +- vm/src/stdlib/signal.rs | 2 +- vm/src/stdlib/sre.rs | 8 ++++---- vm/src/stdlib/thread.rs | 4 ++-- vm/src/stdlib/winreg.rs | 4 ++-- 25 files changed, 75 insertions(+), 73 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a71ceb53b3..174b6baeaf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2390,6 +2390,7 @@ dependencies = [ name = "rustpython-derive" version = "0.4.0" dependencies = [ + "proc-macro2", "rustpython-compiler", "rustpython-derive-impl", "syn 2.0.98", diff --git a/derive-impl/src/from_args.rs b/derive-impl/src/from_args.rs index 2273046ed4..9b06da85e3 100644 --- a/derive-impl/src/from_args.rs +++ b/derive-impl/src/from_args.rs @@ -76,7 +76,6 @@ impl ArgAttribute { return Err(meta.error("Default already set")); } let val = meta.value()?; - let val = val.parse::()?; self.default = Some(Some(val.parse()?)) } else if meta.path.is_ident("default") || meta.path.is_ident("optional") { if self.default.is_none() { @@ -138,9 +137,10 @@ fn generate_field((i, field): (usize, &Field)) -> Result { .map(|x| ::rustpython_vm::convert::TryFromObject::try_from_object(vm, x)).transpose()? }; let ending = if let Some(default) = attr.default { + let ty = &field.ty; let default = default.unwrap_or_else(|| parse_quote!(::std::default::Default::default())); quote! { - .map(::rustpython_vm::function::FromArgOptional::from_inner) + .map(<#ty as ::rustpython_vm::function::FromArgOptional>::from_inner) .unwrap_or_else(|| #default) } } else { diff --git a/derive/Cargo.toml b/derive/Cargo.toml index d38686ce7d..17c0810884 100644 --- a/derive/Cargo.toml +++ b/derive/Cargo.toml @@ -14,6 +14,7 @@ proc-macro = true [dependencies] rustpython-compiler = { workspace = true } rustpython-derive-impl = { workspace = true } +proc-macro2 = { workspace = true } syn = { workspace = true } [lints] diff --git a/stdlib/src/binascii.rs b/stdlib/src/binascii.rs index 65be2e0bdc..f154a2251b 100644 --- a/stdlib/src/binascii.rs +++ b/stdlib/src/binascii.rs @@ -143,7 +143,7 @@ mod decl { #[derive(FromArgs)] struct NewlineArg { - #[pyarg(named, default = "true")] + #[pyarg(named, default = true)] newline: bool, } @@ -151,7 +151,7 @@ mod decl { struct A2bBase64Args { #[pyarg(any)] s: ArgAsciiBuffer, - #[pyarg(named, default = "false")] + #[pyarg(named, default = false)] strict_mode: bool, } @@ -298,7 +298,7 @@ mod decl { struct A2bQpArgs { #[pyarg(any)] data: ArgAsciiBuffer, - #[pyarg(named, default = "false")] + #[pyarg(named, default = false)] header: bool, } #[pyfunction] @@ -366,11 +366,11 @@ mod decl { struct B2aQpArgs { #[pyarg(any)] data: ArgAsciiBuffer, - #[pyarg(named, default = "false")] + #[pyarg(named, default = false)] quotetabs: bool, - #[pyarg(named, default = "true")] + #[pyarg(named, default = true)] istext: bool, - #[pyarg(named, default = "false")] + #[pyarg(named, default = false)] header: bool, } @@ -689,7 +689,7 @@ mod decl { #[derive(FromArgs)] struct BacktickArg { - #[pyarg(named, default = "false")] + #[pyarg(named, default = false)] backtick: bool, } diff --git a/stdlib/src/faulthandler.rs b/stdlib/src/faulthandler.rs index e3cd434731..fcfe423ef5 100644 --- a/stdlib/src/faulthandler.rs +++ b/stdlib/src/faulthandler.rs @@ -34,7 +34,7 @@ mod decl { struct EnableArgs { #[pyarg(any, default)] file: Option, - #[pyarg(any, default = "true")] + #[pyarg(any, default = true)] all_threads: bool, } @@ -50,9 +50,9 @@ mod decl { signum: i64, #[pyarg(any, default)] file: Option, - #[pyarg(any, default = "true")] + #[pyarg(any, default = true)] all_threads: bool, - #[pyarg(any, default = "false")] + #[pyarg(any, default = false)] chain: bool, } diff --git a/stdlib/src/hashlib.rs b/stdlib/src/hashlib.rs index f140515c13..586d825b2c 100644 --- a/stdlib/src/hashlib.rs +++ b/stdlib/src/hashlib.rs @@ -28,7 +28,7 @@ pub mod _hashlib { name: PyStrRef, #[pyarg(any, optional)] data: OptionalArg, - #[pyarg(named, default = "true")] + #[pyarg(named, default = true)] usedforsecurity: bool, } @@ -37,7 +37,7 @@ pub mod _hashlib { pub struct BlakeHashArgs { #[pyarg(positional, optional)] pub data: OptionalArg, - #[pyarg(named, default = "true")] + #[pyarg(named, default = true)] usedforsecurity: bool, } @@ -55,7 +55,7 @@ pub mod _hashlib { pub struct HashArgs { #[pyarg(any, optional)] pub string: OptionalArg, - #[pyarg(named, default = "true")] + #[pyarg(named, default = true)] usedforsecurity: bool, } @@ -331,7 +331,7 @@ pub mod _hashlib { name: PyBuffer, #[pyarg(any, optional)] data: OptionalArg, - #[pyarg(named, default = "true")] + #[pyarg(named, default = true)] digestmod: bool, // TODO: RUSTPYTHON support functions & name functions } diff --git a/stdlib/src/mmap.rs b/stdlib/src/mmap.rs index f254286805..bca367ae4d 100644 --- a/stdlib/src/mmap.rs +++ b/stdlib/src/mmap.rs @@ -191,13 +191,13 @@ mod mmap { fileno: RawFd, #[pyarg(any)] length: isize, - #[pyarg(any, default = "MAP_SHARED")] + #[pyarg(any, default = MAP_SHARED)] flags: libc::c_int, - #[pyarg(any, default = "PROT_WRITE|PROT_READ")] + #[pyarg(any, default = PROT_WRITE|PROT_READ)] prot: libc::c_int, - #[pyarg(any, default = "AccessMode::Default")] + #[pyarg(any, default = AccessMode::Default)] access: AccessMode, - #[pyarg(any, default = "0")] + #[pyarg(any, default = 0)] offset: libc::off_t, } diff --git a/stdlib/src/pystruct.rs b/stdlib/src/pystruct.rs index 2c7aa1ebf7..220970dd20 100644 --- a/stdlib/src/pystruct.rs +++ b/stdlib/src/pystruct.rs @@ -134,7 +134,7 @@ pub(crate) mod _struct { #[derive(FromArgs)] struct UpdateFromArgs { buffer: ArgBytesLike, - #[pyarg(any, default = "0")] + #[pyarg(any, default = 0)] offset: isize, } diff --git a/stdlib/src/select.rs b/stdlib/src/select.rs index d4380b69fa..f89a6c4f03 100644 --- a/stdlib/src/select.rs +++ b/stdlib/src/select.rs @@ -529,9 +529,9 @@ mod decl { #[derive(FromArgs)] pub struct EpollNewArgs { - #[pyarg(any, default = "-1")] + #[pyarg(any, default = -1)] sizehint: i32, - #[pyarg(any, default = "0")] + #[pyarg(any, default = 0)] flags: i32, } @@ -555,7 +555,7 @@ mod decl { struct EpollPollArgs { #[pyarg(any, default)] timeout: poll::TimeoutArg, - #[pyarg(any, default = "-1")] + #[pyarg(any, default = -1)] maxevents: i32, } diff --git a/stdlib/src/socket.rs b/stdlib/src/socket.rs index 988784856f..f4f90a5dc4 100644 --- a/stdlib/src/socket.rs +++ b/stdlib/src/socket.rs @@ -1908,13 +1908,13 @@ mod _socket { #[pyarg(positional)] port: Option>, - #[pyarg(positional, default = "c::AF_UNSPEC")] + #[pyarg(positional, default = c::AF_UNSPEC)] family: i32, - #[pyarg(positional, default = "0")] + #[pyarg(positional, default = 0)] ty: i32, - #[pyarg(positional, default = "0")] + #[pyarg(positional, default = 0)] proto: i32, - #[pyarg(positional, default = "0")] + #[pyarg(positional, default = 0)] flags: i32, } diff --git a/stdlib/src/sqlite.rs b/stdlib/src/sqlite.rs index 97ec193c46..00ebec75a9 100644 --- a/stdlib/src/sqlite.rs +++ b/stdlib/src/sqlite.rs @@ -297,21 +297,21 @@ mod _sqlite { struct ConnectArgs { #[pyarg(any)] database: FsPath, - #[pyarg(any, default = "5.0")] + #[pyarg(any, default = 5.0)] timeout: f64, - #[pyarg(any, default = "0")] + #[pyarg(any, default = 0)] detect_types: c_int, - #[pyarg(any, default = "Some(vm.ctx.empty_str.to_owned())")] + #[pyarg(any, default = Some(vm.ctx.empty_str.to_owned()))] isolation_level: Option, - #[pyarg(any, default = "true")] + #[pyarg(any, default = true)] check_same_thread: bool, - #[pyarg(any, default = "Connection::class(&vm.ctx).to_owned()")] + #[pyarg(any, default = Connection::class(&vm.ctx).to_owned())] factory: PyTypeRef, // TODO: cache statements #[allow(dead_code)] - #[pyarg(any, default = "0")] + #[pyarg(any, default = 0)] cached_statements: c_int, - #[pyarg(any, default = "false")] + #[pyarg(any, default = false)] uri: bool, } @@ -326,13 +326,13 @@ mod _sqlite { struct BackupArgs { #[pyarg(any)] target: PyRef, - #[pyarg(named, default = "-1")] + #[pyarg(named, default = -1)] pages: c_int, #[pyarg(named, optional)] progress: Option, #[pyarg(named, optional)] name: Option, - #[pyarg(named, default = "0.250")] + #[pyarg(named, default = 0.250)] sleep: f64, } @@ -375,7 +375,7 @@ mod _sqlite { row: i64, #[pyarg(named, default)] readonly: bool, - #[pyarg(named, default = "vm.ctx.new_str(stringify!(main))")] + #[pyarg(named, default = vm.ctx.new_str("main"))] name: PyStrRef, } diff --git a/stdlib/src/ssl.rs b/stdlib/src/ssl.rs index c1dcea354f..6cc7f3ed32 100644 --- a/stdlib/src/ssl.rs +++ b/stdlib/src/ssl.rs @@ -351,7 +351,7 @@ mod _ssl { #[derive(FromArgs)] struct Txt2ObjArgs { txt: PyStrRef, - #[pyarg(any, default = "false")] + #[pyarg(any, default = false)] name: bool, } diff --git a/stdlib/src/zlib.rs b/stdlib/src/zlib.rs index 19ed659bbb..40e364f8d4 100644 --- a/stdlib/src/zlib.rs +++ b/stdlib/src/zlib.rs @@ -74,9 +74,9 @@ mod zlib { struct PyFuncCompressArgs { #[pyarg(positional)] data: ArgBytesLike, - #[pyarg(any, default = "Level::new(Z_DEFAULT_COMPRESSION)")] + #[pyarg(any, default = Level::new(Z_DEFAULT_COMPRESSION))] level: Level, - #[pyarg(any, default = "ArgPrimitiveIndex { value: MAX_WBITS }")] + #[pyarg(any, default = ArgPrimitiveIndex { value: MAX_WBITS })] wbits: ArgPrimitiveIndex, } @@ -269,9 +269,9 @@ mod zlib { struct PyFuncDecompressArgs { #[pyarg(positional)] data: ArgBytesLike, - #[pyarg(any, default = "ArgPrimitiveIndex { value: MAX_WBITS }")] + #[pyarg(any, default = ArgPrimitiveIndex { value: MAX_WBITS })] wbits: ArgPrimitiveIndex, - #[pyarg(any, default = "ArgPrimitiveIndex { value: DEF_BUF_SIZE }")] + #[pyarg(any, default = ArgPrimitiveIndex { value: DEF_BUF_SIZE })] bufsize: ArgPrimitiveIndex, } @@ -299,7 +299,7 @@ mod zlib { #[derive(FromArgs)] struct DecompressobjArgs { - #[pyarg(any, default = "ArgPrimitiveIndex { value: MAX_WBITS }")] + #[pyarg(any, default = ArgPrimitiveIndex { value: MAX_WBITS })] wbits: ArgPrimitiveIndex, #[pyarg(any, optional)] zdict: OptionalArg, @@ -450,16 +450,16 @@ mod zlib { #[derive(FromArgs)] #[allow(dead_code)] // FIXME: use args struct CompressobjArgs { - #[pyarg(any, default = "Level::new(Z_DEFAULT_COMPRESSION)")] + #[pyarg(any, default = Level::new(Z_DEFAULT_COMPRESSION))] level: Level, // only DEFLATED is valid right now, it's w/e - #[pyarg(any, default = "DEFLATED")] + #[pyarg(any, default = DEFLATED)] method: i32, - #[pyarg(any, default = "ArgPrimitiveIndex { value: MAX_WBITS }")] + #[pyarg(any, default = ArgPrimitiveIndex { value: MAX_WBITS })] wbits: ArgPrimitiveIndex, - #[pyarg(any, name = "memLevel", default = "DEF_MEM_LEVEL")] + #[pyarg(any, name = "memLevel", default = DEF_MEM_LEVEL)] mem_level: u8, - #[pyarg(any, default = "Z_DEFAULT_STRATEGY")] + #[pyarg(any, default = Z_DEFAULT_STRATEGY)] strategy: i32, #[pyarg(any, optional)] zdict: Option, diff --git a/vm/src/anystr.rs b/vm/src/anystr.rs index efac49d917..6bc8a4dd13 100644 --- a/vm/src/anystr.rs +++ b/vm/src/anystr.rs @@ -10,19 +10,19 @@ use num_traits::{cast::ToPrimitive, sign::Signed}; pub struct SplitArgs { #[pyarg(any, default)] sep: Option, - #[pyarg(any, default = "-1")] + #[pyarg(any, default = -1)] maxsplit: isize, } #[derive(FromArgs)] pub struct SplitLinesArgs { - #[pyarg(any, default = "false")] + #[pyarg(any, default = false)] pub keepends: bool, } #[derive(FromArgs)] pub struct ExpandTabsArgs { - #[pyarg(any, default = "8")] + #[pyarg(any, default = 8)] tabsize: isize, } diff --git a/vm/src/builtins/int.rs b/vm/src/builtins/int.rs index f457bf5ed8..d644343f1c 100644 --- a/vm/src/builtins/int.rs +++ b/vm/src/builtins/int.rs @@ -826,7 +826,7 @@ pub struct IntOptions { #[derive(FromArgs)] struct IntFromByteArgs { bytes: PyBytesInner, - #[pyarg(any, default = "ArgByteOrder::Big")] + #[pyarg(any, default = ArgByteOrder::Big)] byteorder: ArgByteOrder, #[pyarg(named, optional)] signed: OptionalArg, @@ -834,9 +834,9 @@ struct IntFromByteArgs { #[derive(FromArgs)] struct IntToByteArgs { - #[pyarg(any, default = "1")] + #[pyarg(any, default = 1)] length: usize, - #[pyarg(any, default = "ArgByteOrder::Big")] + #[pyarg(any, default = ArgByteOrder::Big)] byteorder: ArgByteOrder, #[pyarg(named, optional)] signed: OptionalArg, diff --git a/vm/src/builtins/list.rs b/vm/src/builtins/list.rs index 1d8b4a30e0..4962ae51e3 100644 --- a/vm/src/builtins/list.rs +++ b/vm/src/builtins/list.rs @@ -91,7 +91,7 @@ pub(crate) struct SortOptions { #[pyarg(named, default)] key: Option, #[pytraverse(skip)] - #[pyarg(named, default = "false")] + #[pyarg(named, default = false)] reverse: bool, } diff --git a/vm/src/stdlib/builtins.rs b/vm/src/stdlib/builtins.rs index f778d02ba3..9dcb35aae9 100644 --- a/vm/src/stdlib/builtins.rs +++ b/vm/src/stdlib/builtins.rs @@ -663,7 +663,7 @@ mod builtins { sep: Option, #[pyarg(named, default)] end: Option, - #[pyarg(named, default = "ArgIntoBool::FALSE")] + #[pyarg(named, default = ArgIntoBool::FALSE)] flush: ArgIntoBool, #[pyarg(named, default)] file: Option, diff --git a/vm/src/stdlib/codecs.rs b/vm/src/stdlib/codecs.rs index 320d839682..c0a091bcf8 100644 --- a/vm/src/stdlib/codecs.rs +++ b/vm/src/stdlib/codecs.rs @@ -109,7 +109,7 @@ mod _codecs { data: ArgBytesLike, #[pyarg(positional, optional)] errors: Option, - #[pyarg(positional, default = "false")] + #[pyarg(positional, default = false)] final_decode: bool, } diff --git a/vm/src/stdlib/io.rs b/vm/src/stdlib/io.rs index 4cf3c058df..33ef118acd 100644 --- a/vm/src/stdlib/io.rs +++ b/vm/src/stdlib/io.rs @@ -3822,7 +3822,7 @@ mod _io { #[derive(FromArgs)] pub struct OpenArgs { - #[pyarg(any, default = "-1")] + #[pyarg(any, default = -1)] pub buffering: isize, #[pyarg(any, default)] pub encoding: Option, @@ -3830,7 +3830,7 @@ mod _io { pub errors: Option, #[pyarg(any, default)] pub newline: Option, - #[pyarg(any, default = "true")] + #[pyarg(any, default = true)] pub closefd: bool, #[pyarg(any, default)] pub opener: Option, @@ -4165,7 +4165,7 @@ mod fileio { name: PyObjectRef, #[pyarg(any, default)] mode: Option, - #[pyarg(any, default = "true")] + #[pyarg(any, default = true)] closefd: bool, #[pyarg(any, default)] opener: Option, diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index f53be8b01b..641ba54dea 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -43,7 +43,7 @@ pub fn errno_err(vm: &VirtualMachine) -> PyBaseExceptionRef { #[allow(dead_code)] #[derive(FromArgs, Default)] pub struct TargetIsDirectory { - #[pyarg(any, default = "false")] + #[pyarg(any, default = false)] pub(crate) target_is_directory: bool, } @@ -117,7 +117,7 @@ impl FromArgs for DirFd { #[derive(FromArgs)] pub(super) struct FollowSymlinks( - #[pyarg(named, name = "follow_symlinks", default = "true")] pub bool, + #[pyarg(named, name = "follow_symlinks", default = true)] pub bool, ); fn bytes_as_osstr<'a>(b: &'a [u8], vm: &VirtualMachine) -> PyResult<&'a ffi::OsStr> { diff --git a/vm/src/stdlib/posix.rs b/vm/src/stdlib/posix.rs index dc5c74cef4..d75629745c 100644 --- a/vm/src/stdlib/posix.rs +++ b/vm/src/stdlib/posix.rs @@ -1628,7 +1628,7 @@ pub mod module { fd: i32, #[pyarg(positional)] fd2: i32, - #[pyarg(any, default = "true")] + #[pyarg(any, default = true)] inheritable: bool, } diff --git a/vm/src/stdlib/signal.rs b/vm/src/stdlib/signal.rs index 0df93833b7..1e1e779e34 100644 --- a/vm/src/stdlib/signal.rs +++ b/vm/src/stdlib/signal.rs @@ -224,7 +224,7 @@ pub(crate) mod _signal { #[derive(FromArgs)] struct SetWakeupFdArgs { fd: WakeupFd, - #[pyarg(named, default = "true")] + #[pyarg(named, default = true)] warn_on_full_buffer: bool, } diff --git a/vm/src/stdlib/sre.rs b/vm/src/stdlib/sre.rs index 6a0a618e2f..7b67c038f4 100644 --- a/vm/src/stdlib/sre.rs +++ b/vm/src/stdlib/sre.rs @@ -163,9 +163,9 @@ mod _sre { #[derive(FromArgs)] struct StringArgs { string: PyObjectRef, - #[pyarg(any, default = "0")] + #[pyarg(any, default = 0)] pos: usize, - #[pyarg(any, default = "sys::MAXSIZE as usize")] + #[pyarg(any, default = sys::MAXSIZE as usize)] endpos: usize, } @@ -174,14 +174,14 @@ mod _sre { // repl: Either, repl: PyObjectRef, string: PyObjectRef, - #[pyarg(any, default = "0")] + #[pyarg(any, default = 0)] count: usize, } #[derive(FromArgs)] struct SplitArgs { string: PyObjectRef, - #[pyarg(any, default = "0")] + #[pyarg(any, default = 0)] maxsplit: isize, } diff --git a/vm/src/stdlib/thread.rs b/vm/src/stdlib/thread.rs index a664d6cdc5..ad80f1f1e1 100644 --- a/vm/src/stdlib/thread.rs +++ b/vm/src/stdlib/thread.rs @@ -52,9 +52,9 @@ pub(crate) mod _thread { #[derive(FromArgs)] struct AcquireArgs { - #[pyarg(any, default = "true")] + #[pyarg(any, default = true)] blocking: bool, - #[pyarg(any, default = "Either::A(-1.0)")] + #[pyarg(any, default = Either::A(-1.0))] timeout: Either, } diff --git a/vm/src/stdlib/winreg.rs b/vm/src/stdlib/winreg.rs index 30fe016148..8d1ca89ddd 100644 --- a/vm/src/stdlib/winreg.rs +++ b/vm/src/stdlib/winreg.rs @@ -149,9 +149,9 @@ mod winreg { struct OpenKeyArgs { key: Hkey, sub_key: Option, - #[pyarg(any, default = "0")] + #[pyarg(any, default = 0)] reserved: i32, - #[pyarg(any, default = "::winreg::enums::KEY_READ")] + #[pyarg(any, default = ::winreg::enums::KEY_READ)] access: u32, }