From 5ff0e4e5de924db40b4a333fe0258a8d29af2dc5 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Thu, 12 Aug 2021 05:53:56 +0900 Subject: [PATCH 1/3] TryFromBorrowedObject for ints --- vm/src/builtins/int.rs | 14 ++++++++------ vm/src/builtins/make_module.rs | 4 ++-- vm/src/builtins/pybool.rs | 10 +++++----- vm/src/pyobject.rs | 25 ++++++++++++++++++++++++- vm/src/stdlib/codecs.rs | 4 ++-- vm/src/stdlib/os.rs | 6 +++--- vm/src/stdlib/resource.rs | 8 ++++---- vm/src/stdlib/select.rs | 4 ++-- vm/src/stdlib/signal.rs | 4 ++-- vm/src/stdlib/socket.rs | 10 +++++----- 10 files changed, 57 insertions(+), 32 deletions(-) diff --git a/vm/src/builtins/int.rs b/vm/src/builtins/int.rs index e7b82eda1..f4f418bce 100644 --- a/vm/src/builtins/int.rs +++ b/vm/src/builtins/int.rs @@ -19,8 +19,9 @@ use crate::slots::{Comparable, Hashable, PyComparisonOp}; use crate::VirtualMachine; use crate::{bytesinner::PyBytesInner, byteslike::try_bytes_like}; use crate::{ - IdProtocol, IntoPyObject, IntoPyResult, PyArithmaticValue, PyClassImpl, PyComparisonValue, - PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol, + try_value_from_borrowed_object, IdProtocol, IntoPyObject, IntoPyResult, PyArithmaticValue, + PyClassImpl, PyComparisonValue, PyContext, PyObjectRef, PyRef, PyResult, PyValue, + TryFromBorrowedObject, TypeProtocol, }; use rustpython_common::hash; @@ -101,10 +102,11 @@ where macro_rules! impl_try_from_object_int { ($(($t:ty, $to_prim:ident),)*) => {$( - impl TryFromObject for $t { - fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { - let int = PyIntRef::try_from_object(vm, obj)?; - try_to_primitive(&int.value, vm) + impl TryFromBorrowedObject for $t { + fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult { + try_value_from_borrowed_object(vm, obj, |int: &PyInt| { + try_to_primitive(int.as_bigint(), vm) + }) } } )*}; diff --git a/vm/src/builtins/make_module.rs b/vm/src/builtins/make_module.rs index 51f80f041..0fcdfc47c 100644 --- a/vm/src/builtins/make_module.rs +++ b/vm/src/builtins/make_module.rs @@ -13,7 +13,7 @@ mod decl { use crate::builtins::code::PyCodeRef; use crate::builtins::dict::PyDictRef; use crate::builtins::function::{PyCellRef, PyFunctionRef}; - use crate::builtins::int::PyIntRef; + use crate::builtins::int::{self, PyIntRef}; use crate::builtins::iter::{PyCallableIterator, PySequenceIterator}; use crate::builtins::list::{PyList, SortOptions}; use crate::builtins::pybool::IntoPyBool; @@ -161,7 +161,7 @@ mod decl { let flags = args .flags - .map_or(Ok(0), |v| i32::try_from_object(vm, v.into_object()))?; + .map_or(Ok(0), |v| int::try_to_primitive(v.as_bigint(), vm))?; if (flags & ast::PY_COMPILE_FLAG_AST_ONLY).is_zero() { #[cfg(not(feature = "rustpython-compiler"))] diff --git a/vm/src/builtins/pybool.rs b/vm/src/builtins/pybool.rs index 81e8a01f4..6c5821c0b 100644 --- a/vm/src/builtins/pybool.rs +++ b/vm/src/builtins/pybool.rs @@ -6,8 +6,8 @@ use super::pystr::PyStrRef; use crate::function::OptionalArg; use crate::vm::VirtualMachine; use crate::{ - IdProtocol, IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyResult, TryFromObject, - TypeProtocol, + IdProtocol, IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyResult, TryFromBorrowedObject, + TryFromObject, TypeProtocol, }; impl IntoPyObject for bool { @@ -16,10 +16,10 @@ impl IntoPyObject for bool { } } -impl TryFromObject for bool { - fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { +impl TryFromBorrowedObject for bool { + fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult { if obj.isinstance(&vm.ctx.types.int_type) { - Ok(get_value(&obj)) + Ok(get_value(obj)) } else { Err(vm.new_type_error(format!("Expected type bool, not {}", obj.class().name))) } diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index dae5a3e60..9467ef572 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -408,6 +408,28 @@ impl Default for PyContext { } } +pub(crate) fn try_value_from_borrowed_object( + vm: &VirtualMachine, + obj: &PyObjectRef, + f: F, +) -> PyResult +where + T: PyValue, + F: Fn(&T) -> PyResult, +{ + let class = T::class(vm); + let special; + let py_ref = if obj.isinstance(class) { + obj.downcast_ref() + .ok_or_else(|| pyref_payload_error(vm, class, obj))? + } else { + special = T::special_retrieve(vm, obj) + .unwrap_or_else(|| Err(pyref_type_error(vm, class, obj)))?; + &special + }; + f(py_ref) +} + impl TryFromObject for PyRef where T: PyValue, @@ -435,7 +457,8 @@ fn pyref_payload_error( &*obj.borrow().class().name, )) } -fn pyref_type_error( + +pub(crate) fn pyref_type_error( vm: &VirtualMachine, class: &PyTypeRef, obj: impl std::borrow::Borrow, diff --git a/vm/src/stdlib/codecs.rs b/vm/src/stdlib/codecs.rs index 1a2b7f4e6..45f730af2 100644 --- a/vm/src/stdlib/codecs.rs +++ b/vm/src/stdlib/codecs.rs @@ -11,7 +11,7 @@ mod _codecs { use crate::exceptions::PyBaseExceptionRef; use crate::function::FuncArgs; use crate::VirtualMachine; - use crate::{IdProtocol, PyObjectRef, PyResult, TryFromObject}; + use crate::{IdProtocol, PyObjectRef, PyResult, TryFromBorrowedObject}; #[pyfunction] fn register(search_function: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { @@ -156,7 +156,7 @@ mod _codecs { .ok_or_else(tuple_err)? .clone(); let restart = - isize::try_from_object(vm, restart.clone()).map_err(|_| tuple_err())?; + isize::try_from_borrowed_object(vm, restart).map_err(|_| tuple_err())?; let restart = if restart < 0 { // will still be out of bounds if it underflows ¯\_(ツ)_/¯ data.len().wrapping_sub(restart.unsigned_abs()) diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index 02a1cce2f..ce3ec191c 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -30,7 +30,7 @@ use crate::utils::Either; use crate::vm::{ReprGuard, VirtualMachine}; use crate::{ IntoPyObject, ItemProtocol, PyObjectRef, PyRef, PyResult, PyStructSequence, PyValue, - StaticType, TryFromObject, TypeProtocol, + StaticType, TryFromBorrowedObject, TryFromObject, TypeProtocol, }; #[cfg(unix)] @@ -1654,7 +1654,7 @@ mod _os { #[pyfunction] fn truncate(path: PyObjectRef, length: Offset, vm: &VirtualMachine) -> PyResult<()> { - if let Ok(fd) = i32::try_from_object(vm, path.clone()) { + if let Ok(fd) = i32::try_from_borrowed_object(vm, &path) { return ftruncate(fd, length, vm); } let path = PyPathLike::try_from_object(vm, path)?; @@ -2867,7 +2867,7 @@ mod posix { "Each file_actions element must be a non-empty tuple".to_owned(), ) })?; - let id = i32::try_from_object(vm, id.clone())?; + let id = i32::try_from_borrowed_object(vm, id)?; let id = PosixSpawnFileActionIdentifier::try_from(id).map_err(|_| { vm.new_type_error("Unknown file_actions identifier".to_owned()) })?; diff --git a/vm/src/stdlib/resource.rs b/vm/src/stdlib/resource.rs index 8a4628ccb..dffee993f 100644 --- a/vm/src/stdlib/resource.rs +++ b/vm/src/stdlib/resource.rs @@ -5,7 +5,7 @@ mod resource { use super::super::os; use crate::exceptions::IntoPyException; use crate::VirtualMachine; - use crate::{IntoPyObject, PyObjectRef, PyResult, PyStructSequence, TryFromObject}; + use crate::{IntoPyObject, PyObjectRef, PyResult, PyStructSequence, TryFromBorrowedObject}; use std::{io, mem}; cfg_if::cfg_if! { @@ -111,9 +111,9 @@ mod resource { } struct Limits(libc::rlimit); - impl TryFromObject for Limits { - fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { - let seq = vm.extract_elements::(&obj)?; + impl TryFromBorrowedObject for Limits { + fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult { + let seq = vm.extract_elements::(obj)?; match *seq { [cur, max] => Ok(Self(libc::rlimit { rlim_cur: cur & RLIM_INFINITY, diff --git a/vm/src/stdlib/select.rs b/vm/src/stdlib/select.rs index b6e81710d..c77587a6a 100644 --- a/vm/src/stdlib/select.rs +++ b/vm/src/stdlib/select.rs @@ -1,5 +1,5 @@ use crate::vm::VirtualMachine; -use crate::{PyObjectRef, PyResult, TryFromObject}; +use crate::{PyObjectRef, PyResult, TryFromBorrowedObject, TryFromObject}; use std::{io, mem}; pub(crate) fn make_module(vm: &VirtualMachine) -> PyObjectRef { @@ -72,7 +72,7 @@ struct Selectable { impl TryFromObject for Selectable { fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { - let fno = RawFd::try_from_object(vm, obj.clone()).or_else(|_| { + let fno = RawFd::try_from_borrowed_object(vm, &obj).or_else(|_| { let meth = vm.get_method_or_type_error(obj.clone(), "fileno", || { "select arg must be an int or object with a fileno() method".to_owned() })?; diff --git a/vm/src/stdlib/signal.rs b/vm/src/stdlib/signal.rs index d1b8eb8c2..609baf886 100644 --- a/vm/src/stdlib/signal.rs +++ b/vm/src/stdlib/signal.rs @@ -1,6 +1,6 @@ use crate::exceptions::IntoPyException; use crate::vm::{VirtualMachine, NSIG}; -use crate::{PyObjectRef, PyResult, TryFromObject}; +use crate::{PyObjectRef, PyResult, TryFromBorrowedObject}; use std::sync::atomic::{self, AtomicBool, Ordering}; @@ -81,7 +81,7 @@ fn _signal_signal( .as_deref() .ok_or_else(|| vm.new_value_error("signal only works in main thread".to_owned()))?; - let sig_handler = match usize::try_from_object(vm, handler.clone()).ok() { + let sig_handler = match usize::try_from_borrowed_object(vm, &handler).ok() { Some(SIG_DFL) => SIG_DFL, Some(SIG_IGN) => SIG_IGN, None if vm.is_callable(&handler) => run_signal as libc::sighandler_t, diff --git a/vm/src/stdlib/socket.rs b/vm/src/stdlib/socket.rs index f35e9fc85..bdf3ad4c3 100644 --- a/vm/src/stdlib/socket.rs +++ b/vm/src/stdlib/socket.rs @@ -21,8 +21,8 @@ use crate::function::{FuncArgs, OptionalArg, OptionalOption}; use crate::utils::Either; use crate::VirtualMachine; use crate::{ - IntoPyObject, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, StaticType, TryFromObject, - TypeProtocol, + IntoPyObject, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, StaticType, + TryFromBorrowedObject, TryFromObject, TypeProtocol, }; #[cfg(unix)] @@ -970,7 +970,7 @@ impl TryFromObject for Address { impl Address { fn from_tuple(tuple: &[PyObjectRef], vm: &VirtualMachine) -> PyResult { let host = PyStrRef::try_from_object(vm, tuple[0].clone())?; - let port = i32::try_from_object(vm, tuple[1].clone())?; + let port = i32::try_from_borrowed_object(vm, &tuple[1])?; let port = port .to_u16() .ok_or_else(|| vm.new_overflow_error("port must be 0-65535.".to_owned()))?; @@ -980,12 +980,12 @@ impl Address { let addr = Address::from_tuple(tuple, vm)?; let flowinfo = tuple .get(2) - .map(|obj| u32::try_from_object(vm, obj.clone())) + .map(|obj| u32::try_from_borrowed_object(vm, obj)) .transpose()? .unwrap_or(0); let scopeid = tuple .get(3) - .map(|obj| u32::try_from_object(vm, obj.clone())) + .map(|obj| u32::try_from_borrowed_object(vm, obj)) .transpose()? .unwrap_or(0); if flowinfo > 0xfffff { From 10fe2d4763c9e376268ddc75a8936c10fe7f7e90 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Tue, 17 Aug 2021 01:32:25 +0300 Subject: [PATCH 2/3] Attempt to fix the failing CI --- Cargo.lock | 81 +++++++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 004a5e5dd..3ccef5e02 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -57,9 +57,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.42" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486" +checksum = "28ae2b3dec75a406790005a200b1bd89785afc02517a00ca99ecfe093ee9e6cf" [[package]] name = "approx" @@ -901,9 +901,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1b21a2971cea49ca4613c0e9fe8225ecaf5de64090fddc6002284726e9244" +checksum = "58019516c1403ac45b106c9fc4e8fcbd77a78e98b014c619d1506338902ccfa4" dependencies = [ "console", "lazy_static 1.4.0", @@ -956,9 +956,9 @@ checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" [[package]] name = "js-sys" -version = "0.3.51" +version = "0.3.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062" +checksum = "ce791b7ca6638aae45be056e068fc756d871eb3b3b10b8efa62d1c9cec616752" dependencies = [ "wasm-bindgen", ] @@ -1118,9 +1118,9 @@ checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] name = "matches" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "md-5" @@ -1184,21 +1184,22 @@ dependencies = [ [[package]] name = "nix" -version = "0.20.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a" +checksum = "df8e5e343312e7fbeb2a52139114e9e702991ef9c2aea6817ff2440b35647d56" dependencies = [ "bitflags", "cc", "cfg-if 1.0.0", "libc", + "memoffset", ] [[package]] name = "nix" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1e25ee6b412c2a1e3fcb6a4499a5c1bfe7f43e014bdce9a6b6666e5aa2d187" +checksum = "e7555d6c7164cc913be1ce7f95cbecdabda61eb2ccd89008524af306fb7f5031" dependencies = [ "bitflags", "cc", @@ -1272,9 +1273,9 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5adf0198d427ee515335639f275e806ca01acf9f07d7cf14bb36a10532a6169" +checksum = "ee2c8fd66061a707503d515639b8af10fd3807a5b5ee6959f7ff1bd303634bd5" dependencies = [ "derivative", "num_enum_derive", @@ -1282,9 +1283,9 @@ dependencies = [ [[package]] name = "num_enum_derive" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1def5a3f69d4707d8a040b12785b98029a39e8c610ae685c7f6265669767482" +checksum = "474fd1d096da3ad17084694eebed40ba09c4a36c5255cd772bd8b98859cc562e" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1373,7 +1374,7 @@ dependencies = [ "cfg-if 1.0.0", "instant", "libc", - "redox_syscall 0.2.9", + "redox_syscall 0.2.10", "smallvec", "winapi", ] @@ -1407,9 +1408,9 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc1437ada0f3a97d538f0bb608137bf53c53969028cab74c89893e1e9a12f0e" +checksum = "d43f3220d96e0080cc9ea234978ccd80d904eafb17be31bb0f76daaea6493082" dependencies = [ "phf_shared 0.9.0", "rand", @@ -1649,9 +1650,9 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "redox_syscall" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" dependencies = [ "bitflags", ] @@ -1663,7 +1664,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" dependencies = [ "getrandom", - "redox_syscall 0.2.9", + "redox_syscall 0.2.10", ] [[package]] @@ -1922,7 +1923,7 @@ dependencies = [ "md-5", "memchr", "mt19937", - "nix 0.22.0", + "nix 0.22.1", "num-bigint", "num-complex", "num-integer", @@ -2020,7 +2021,7 @@ dependencies = [ "libc", "log", "memchr", - "nix 0.20.0", + "nix 0.20.1", "radix_trie", "scopeguard", "smallvec", @@ -2090,9 +2091,9 @@ dependencies = [ [[package]] name = "serde_cbor" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" dependencies = [ "half", "serde", @@ -2697,9 +2698,9 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasm-bindgen" -version = "0.2.74" +version = "0.2.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd" +checksum = "b608ecc8f4198fe8680e2ed18eccab5f0cd4caaf3d83516fa5fb2e927fda2586" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -2707,9 +2708,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.74" +version = "0.2.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900" +checksum = "580aa3a91a63d23aac5b6b267e2d13cb4f363e31dce6c352fca4752ae12e479f" dependencies = [ "bumpalo", "lazy_static 1.4.0", @@ -2722,9 +2723,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.24" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fba7978c679d53ce2d0ac80c8c175840feb849a161664365d1287b41f2e67f1" +checksum = "16646b21c3add8e13fdb8f20172f8a28c3dbf62f45406bcff0233188226cfe0c" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -2734,9 +2735,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.74" +version = "0.2.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4" +checksum = "171ebf0ed9e1458810dfcb31f2e766ad6b3a89dbda42d8901f2b268277e5f09c" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2744,9 +2745,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.74" +version = "0.2.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97" +checksum = "6c2657dd393f03aa2a659c25c6ae18a13a4048cebd220e147933ea837efc589f" dependencies = [ "proc-macro2", "quote", @@ -2757,15 +2758,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.74" +version = "0.2.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f" +checksum = "2e0c4a743a309662d45f4ede961d7afa4ba4131a59a639f29b0069c3798bbcc2" [[package]] name = "web-sys" -version = "0.3.51" +version = "0.3.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e828417b379f3df7111d3a2a9e5753706cae29c41f7c4029ee9fd77f3e09e582" +checksum = "01c70a82d842c9979078c772d4a1344685045f1a5628f677c2b2eab4dd7d2696" dependencies = [ "js-sys", "wasm-bindgen", From f6fbea3019776224a83a9e2d80e76106d841d40d Mon Sep 17 00:00:00 2001 From: Tetramad Date: Sat, 14 Aug 2021 14:05:16 +0900 Subject: [PATCH 3/3] Update pprint module to Python3.8 Add `sort_dicts` parameter to several functions and new `pp` function. --- Lib/pprint.py | 54 ++++++++++++++++++++++++++--------------- Lib/test/test_pprint.py | 4 --- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/Lib/pprint.py b/Lib/pprint.py index bcf2eedeb..3d1024818 100644 --- a/Lib/pprint.py +++ b/Lib/pprint.py @@ -41,33 +41,38 @@ import types as _types from io import StringIO as _StringIO __all__ = ["pprint","pformat","isreadable","isrecursive","saferepr", - "PrettyPrinter"] + "PrettyPrinter", "pp"] def pprint(object, stream=None, indent=1, width=80, depth=None, *, - compact=False): + compact=False, sort_dicts=True): """Pretty-print a Python object to a stream [default is sys.stdout].""" printer = PrettyPrinter( stream=stream, indent=indent, width=width, depth=depth, - compact=compact) + compact=compact, sort_dicts=sort_dicts) printer.pprint(object) -def pformat(object, indent=1, width=80, depth=None, *, compact=False): +def pformat(object, indent=1, width=80, depth=None, *, + compact=False, sort_dicts=True): """Format a Python object into a pretty-printed representation.""" return PrettyPrinter(indent=indent, width=width, depth=depth, - compact=compact).pformat(object) + compact=compact, sort_dicts=sort_dicts).pformat(object) + +def pp(object, *args, sort_dicts=False, **kwargs): + """Pretty-print a Python object""" + pprint(object, *args, sort_dicts=sort_dicts, **kwargs) def saferepr(object): """Version of repr() which can handle recursive data structures.""" - return _safe_repr(object, {}, None, 0)[0] + return _safe_repr(object, {}, None, 0, True)[0] def isreadable(object): """Determine if saferepr(object) is readable by eval().""" - return _safe_repr(object, {}, None, 0)[1] + return _safe_repr(object, {}, None, 0, True)[1] def isrecursive(object): """Determine if object requires a recursive representation.""" - return _safe_repr(object, {}, None, 0)[2] + return _safe_repr(object, {}, None, 0, True)[2] class _safe_key: """Helper function for key functions when sorting unorderable objects. @@ -97,7 +102,7 @@ def _safe_tuple(t): class PrettyPrinter: def __init__(self, indent=1, width=80, depth=None, stream=None, *, - compact=False): + compact=False, sort_dicts=True): """Handle pretty printing operations onto a stream using a set of configured parameters. @@ -117,6 +122,9 @@ class PrettyPrinter: compact If true, several items will be combined in one line. + sort_dicts + If true, dict keys are sorted. + """ indent = int(indent) width = int(width) @@ -134,6 +142,7 @@ class PrettyPrinter: else: self._stream = _sys.stdout self._compact = bool(compact) + self._sort_dicts = sort_dicts def pprint(self, object): self._format(object, self._stream, 0, 0, {}, 0) @@ -184,7 +193,10 @@ class PrettyPrinter: write((self._indent_per_level - 1) * ' ') length = len(object) if length: - items = sorted(object.items(), key=_safe_tuple) + if self._sort_dicts: + items = sorted(object.items(), key=_safe_tuple) + else: + items = object.items() self._format_dict_items(items, stream, indent, allowance + 1, context, level) write('}') @@ -402,7 +414,7 @@ class PrettyPrinter: and flags indicating whether the representation is 'readable' and whether the object represents a recursive construct. """ - return _safe_repr(object, context, maxlevels, level) + return _safe_repr(object, context, maxlevels, level, self._sort_dicts) def _pprint_default_dict(self, object, stream, indent, allowance, context, level): if not len(object): @@ -487,7 +499,7 @@ class PrettyPrinter: # Return triple (repr_string, isreadable, isrecursive). -def _safe_repr(object, context, maxlevels, level): +def _safe_repr(object, context, maxlevels, level, sort_dicts): typ = type(object) if typ in _builtin_scalars: return repr(object), True, False @@ -507,11 +519,13 @@ def _safe_repr(object, context, maxlevels, level): components = [] append = components.append level += 1 - saferepr = _safe_repr - items = sorted(object.items(), key=_safe_tuple) + if sort_dicts: + items = sorted(object.items(), key=_safe_tuple) + else: + items = object.items() for k, v in items: - krepr, kreadable, krecur = saferepr(k, context, maxlevels, level) - vrepr, vreadable, vrecur = saferepr(v, context, maxlevels, level) + krepr, kreadable, krecur = _safe_repr(k, context, maxlevels, level, sort_dicts) + vrepr, vreadable, vrecur = _safe_repr(v, context, maxlevels, level, sort_dicts) append("%s: %s" % (krepr, vrepr)) readable = readable and kreadable and vreadable if krecur or vrecur: @@ -543,7 +557,7 @@ def _safe_repr(object, context, maxlevels, level): append = components.append level += 1 for o in object: - orepr, oreadable, orecur = _safe_repr(o, context, maxlevels, level) + orepr, oreadable, orecur = _safe_repr(o, context, maxlevels, level, sort_dicts) append(orepr) if not oreadable: readable = False @@ -568,9 +582,9 @@ def _perfcheck(object=None): if object is None: object = [("string", (1, 2), [3, 4], {5: 6, 7: 8})] * 100000 p = PrettyPrinter() - t1 = time.time() - _safe_repr(object, {}, None, 0) - t2 = time.time() + t1 = time.perf_counter() + _safe_repr(object, {}, None, 0, True) + t2 = time.perf_counter() p.pformat(object) t3 = time.time() print("_safe_repr:", t2 - t1) diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py index 4d841867d..642d9368d 100644 --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -76,8 +76,6 @@ class QueryTestCase(unittest.TestCase): self.b = list(range(200)) self.a[-12] = self.b - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_init(self): pp = pprint.PrettyPrinter() pp = pprint.PrettyPrinter(indent=4, width=40, depth=5, @@ -300,8 +298,6 @@ class QueryTestCase(unittest.TestCase): self.assertEqual(pprint.pformat({"xy\tab\n": (3,), 5: [[]], (): {}}), r"{5: [[]], 'xy\tab\n': (3,), (): {}}") - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_sort_dict(self): d = dict.fromkeys('cba') self.assertEqual(pprint.pformat(d, sort_dicts=False), "{'c': None, 'b': None, 'a': None}")