diff --git a/Cargo.lock b/Cargo.lock index a8b5ebc71..9ca4e6a0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -703,9 +703,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f" dependencies = [ "atty", - "humantime", "log", - "regex", "termcolor", ] @@ -915,12 +913,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296f72d53a89096cbc9a88c9547ee8dfe793388674620e2207593d370550ac" -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "indexmap" version = "1.6.2" @@ -1267,17 +1259,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-iter" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - [[package]] name = "num-rational" version = "0.4.0" @@ -2056,7 +2037,6 @@ dependencies = [ "num-bigint", "num-complex", "num-integer", - "num-iter", "num-rational", "num-traits", "num_cpus", @@ -2069,7 +2049,6 @@ dependencies = [ "puruspe", "rand 0.8.3", "rand_core 0.6.2", - "regex", "result-like", "rustc_version_runtime", "rustpython-ast", @@ -2084,7 +2063,6 @@ dependencies = [ "rustyline", "schannel", "serde", - "serde_json", "sha-1", "sha2", "sha3", diff --git a/Cargo.toml b/Cargo.toml index 36ab0ded9..a6ca39e48 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ license = "MIT" include = ["LICENSE", "Cargo.toml", "src/**/*.rs"] [workspace] +resolver = "2" members = [ ".", "ast", "bytecode", "common", "compiler", "compiler/porcelain", "derive", "jit", "parser", "vm", "vm/pylib-crate", "wasm/lib", @@ -26,7 +27,7 @@ ssl = ["rustpython-vm/ssl"] [dependencies] log = "0.4" -env_logger = "0.8.3" +env_logger = { version = "0.8", default-features = false, features = ["atty", "termcolor"] } clap = "2.33" rustpython-compiler = { path = "compiler/porcelain", version = "0.1.1" } rustpython-parser = { path = "parser", version = "0.1.1" } diff --git a/Lib/json/__init__.py b/Lib/json/__init__.py index 4b7d8897b..1ba8b48bd 100644 --- a/Lib/json/__init__.py +++ b/Lib/json/__init__.py @@ -107,11 +107,6 @@ from .decoder import JSONDecoder, JSONDecodeError from .encoder import JSONEncoder import codecs -_use_serde_json = False -def use_serde_json(x=True): - global _use_serde_json - _use_serde_json = x - _default_encoder = JSONEncoder( skipkeys=False, ensure_ascii=True, @@ -359,13 +354,6 @@ def loads(s, *, cls=None, object_hook=None, parse_float=None, if (cls is None and object_hook is None and parse_int is None and parse_float is None and parse_constant is None and object_pairs_hook is None and not kw): - if _use_serde_json: - try: - import _serde_json - except ImportError: - pass - else: - return _serde_json.decode(s) return _default_decoder.decode(s) if cls is None: cls = JSONDecoder diff --git a/vm/Cargo.toml b/vm/Cargo.toml index 0335576bf..d983ba6c3 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -22,7 +22,7 @@ ast = ["rustpython-ast"] compiler = ["rustpython-compiler", "rustpython-compiler-core", "ast"] parser = ["rustpython-parser", "ast"] -ssl = ["openssl", "openssl-sys", "openssl-probe"] +ssl = ["openssl", "openssl-sys", "openssl-probe", "foreign-types-shared"] [dependencies] # Crypto: @@ -38,7 +38,6 @@ num-bigint = { version = "0.4.0", features = ["serde"] } num-traits = "0.2.8" num-integer = "0.1.41" num-rational = "0.4.0" -num-iter = "0.1.39" rand = "0.8" rand_core = "0.6" getrandom = { version = "0.2", features = ["js"] } @@ -52,8 +51,6 @@ rustpython-bytecode = { path = "../bytecode", version = "0.1.2" } rustpython-jit = { path = "../jit", optional = true, version = "0.1.2" } rustpython-pylib = { path = "pylib-crate", optional = true, version = "0.1.0" } serde = { version = "1.0.66", features = ["derive"] } -serde_json = "1.0" -regex = "1" rustc_version_runtime = "0.2.0" puruspe = "0.1" caseless = "0.2.1" @@ -73,7 +70,6 @@ paste = "1.0.5" base64 = "0.13" is-macro = "0.1" result-like = "^0.3" -foreign-types-shared = "0.1" num_enum = "0.5" bstr = "0.2.12" crossbeam-utils = "0.8" @@ -127,6 +123,7 @@ openssl = { version = "0.10.32", features = ["vendored"], optional = true } openssl-sys = { version = "0.9", optional = true } openssl-probe = { version = "0.1", optional = true } which = "4.0" +foreign-types-shared = { version = "0.1", optional = true } [target.'cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))'.dependencies] num_cpus = "1" diff --git a/vm/src/exceptions.rs b/vm/src/exceptions.rs index 2799a7d26..9ae76fab4 100644 --- a/vm/src/exceptions.rs +++ b/vm/src/exceptions.rs @@ -11,9 +11,9 @@ use crate::pyobject::{ BorrowValue, IntoPyObject, PyClassImpl, PyContext, PyIterable, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol, }; +use crate::sysmodule; use crate::types::create_type_with_slots; use crate::VirtualMachine; -use crate::{py_serde, sysmodule}; use crossbeam_utils::atomic::AtomicCell; use itertools::Itertools; @@ -175,7 +175,7 @@ pub fn print_exception(vm: &VirtualMachine, exc: PyBaseExceptionRef) { let _ = write_exception(&mut stderr, vm, exc); } else { eprintln!("{}\nlost sys.stderr", errstr); - let _ = write_exception(&mut io::stderr(), vm, exc); + let _ = write_exception(&mut py_io::IoWriter(io::stderr()), vm, exc); } }; if let Ok(excepthook) = vm.get_attribute(vm.sys_module.clone(), "excepthook") { @@ -797,7 +797,7 @@ impl serde::Serialize for SerializeException<'_> { "context", &self.exc.context().as_ref().map(|e| Self::new(self.vm, e)), )?; - struc.serialize_field("suppress_context", &self.exc.suppress_context.load())?; + struc.serialize_field("suppress_context", &self.exc.get_suppress_context())?; let args = { struct Args<'vm>(&'vm VirtualMachine, PyTupleRef); @@ -807,7 +807,7 @@ impl serde::Serialize for SerializeException<'_> { self.1 .borrow_value() .iter() - .map(|arg| py_serde::PyObjectSerializer::new(self.0, arg)), + .map(|arg| crate::py_serde::PyObjectSerializer::new(self.0, arg)), ) } } @@ -816,9 +816,9 @@ impl serde::Serialize for SerializeException<'_> { struc.serialize_field("args", &args)?; let rendered = { - let mut rendered = Vec::::new(); + let mut rendered = String::new(); write_exception(&mut rendered, self.vm, &self.exc).map_err(S::Error::custom)?; - String::from_utf8(rendered).map_err(S::Error::custom)? + rendered }; struc.serialize_field("rendered", &rendered)?; diff --git a/vm/src/lib.rs b/vm/src/lib.rs index 3a92aed60..f7d90bb35 100644 --- a/vm/src/lib.rs +++ b/vm/src/lib.rs @@ -59,7 +59,7 @@ mod frozen; pub mod function; pub mod import; pub mod iterator; -mod py_io; +pub mod py_io; pub mod py_serde; pub mod pyobject; mod pyobjectrc; diff --git a/vm/src/py_io.rs b/vm/src/py_io.rs index 17c007772..0ab7dbef7 100644 --- a/vm/src/py_io.rs +++ b/vm/src/py_io.rs @@ -3,20 +3,49 @@ use crate::builtins::pystr::PyStr; use crate::exceptions::PyBaseExceptionRef; use crate::pyobject::{BorrowValue, PyObjectRef, PyResult}; use crate::VirtualMachine; -use std::{fmt, io}; +use std::{fmt, io, ops}; pub trait Write { type Error; fn write_fmt(&mut self, args: fmt::Arguments) -> Result<(), Self::Error>; } -impl Write for W +#[repr(transparent)] +pub struct IoWriter(pub T); + +impl IoWriter { + pub fn from_ref(x: &mut T) -> &mut Self { + // SAFETY: IoWriter is repr(transparent) over T + unsafe { &mut *(x as *mut T as *mut Self) } + } +} + +impl ops::Deref for IoWriter { + type Target = T; + fn deref(&self) -> &T { + &self.0 + } +} +impl ops::DerefMut for IoWriter { + fn deref_mut(&mut self) -> &mut T { + &mut self.0 + } +} + +impl Write for IoWriter where W: io::Write, { type Error = io::Error; fn write_fmt(&mut self, args: fmt::Arguments) -> io::Result<()> { - ::write_fmt(self, args) + ::write_fmt(&mut self.0, args) + } +} + +impl Write for String { + type Error = fmt::Error; + fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result { + ::write_fmt(self, args) } } diff --git a/vm/src/stdlib/math.rs b/vm/src/stdlib/math.rs index fcd100e87..a2cd36cf8 100644 --- a/vm/src/stdlib/math.rs +++ b/vm/src/stdlib/math.rs @@ -473,13 +473,20 @@ fn math_fsum(iter: PyIterable, vm: &VirtualMachine) -> PyResult PyResult { let value = value.borrow_value(); + let one = BigInt::one(); if value.is_negative() { return Err(vm.new_value_error("factorial() not defined for negative values".to_owned())); - } else if *value <= BigInt::one() { - return Ok(BigInt::from(1u64)); + } else if *value <= one { + return Ok(one); } - let ret: BigInt = num_iter::range_inclusive(BigInt::from(1u64), value.clone()).product(); - Ok(ret) + // start from 2, since we know that value > 1 and 1*2=2 + let mut current = one + 1; + let mut product = BigInt::from(2u8); + while current < *value { + current += 1; + product *= ¤t; + } + Ok(product) } fn math_modf(x: IntoPyFloat) -> (f64, f64) { diff --git a/vm/src/stdlib/mod.rs b/vm/src/stdlib/mod.rs index 497a219c6..fccbc49df 100644 --- a/vm/src/stdlib/mod.rs +++ b/vm/src/stdlib/mod.rs @@ -26,8 +26,8 @@ mod operator; mod platform; pub(crate) mod pystruct; mod random; -mod re; -mod serde_json; +// TODO: maybe make this an extension module, if we ever get those +// mod re; #[cfg(not(target_arch = "wasm32"))] pub mod socket; mod sre; @@ -114,9 +114,7 @@ pub fn get_module_inits() -> StdlibMap { "math" => math::make_module, "_operator" => operator::make_module, "_platform" => platform::make_module, - "regex_crate" => re::make_module, "_random" => random::make_module, - "_serde_json" => serde_json::make_module, "_sre" => sre::make_module, "_string" => string::make_module, "_struct" => pystruct::make_module, diff --git a/vm/src/stdlib/serde_json.rs b/vm/src/stdlib/serde_json.rs deleted file mode 100644 index 20d4af320..000000000 --- a/vm/src/stdlib/serde_json.rs +++ /dev/null @@ -1,39 +0,0 @@ -pub(crate) use _serde_json::make_module; - -#[pymodule] -mod _serde_json { - use crate::builtins::pystr::PyStrRef; - use crate::common::borrow::BorrowValue; - use crate::exceptions::PyBaseExceptionRef; - use crate::py_serde; - use crate::pyobject::{PyResult, TryFromObject}; - use crate::VirtualMachine; - - #[pyfunction] - fn decode(s: PyStrRef, vm: &VirtualMachine) -> PyResult { - let res = (|| -> serde_json::Result<_> { - let mut de = serde_json::Deserializer::from_str(s.borrow_value()); - let res = py_serde::deserialize(vm, &mut de)?; - de.end()?; - Ok(res) - })(); - - res.map_err(|err| match json_exception(err, s, vm) { - Ok(x) | Err(x) => x, - }) - } - - fn json_exception( - err: serde_json::Error, - s: PyStrRef, - vm: &VirtualMachine, - ) -> PyResult { - let decode_error = vm.try_class("json", "JSONDecodeError")?; - let from_serde = vm.get_attribute(decode_error.into_object(), "_from_serde")?; - let mut err_msg = err.to_string(); - let pos = err_msg.rfind(" at line ").unwrap(); - err_msg.truncate(pos); - let decode_error = vm.invoke(&from_serde, (err_msg, s, err.line(), err.column()))?; - PyBaseExceptionRef::try_from_object(vm, decode_error) - } -} diff --git a/vm/src/stdlib/thread.rs b/vm/src/stdlib/thread.rs index ccd14f386..7eece813d 100644 --- a/vm/src/stdlib/thread.rs +++ b/vm/src/stdlib/thread.rs @@ -5,12 +5,13 @@ use crate::builtins::tuple::PyTupleRef; /// Implementation of the _thread module use crate::exceptions::{self, IntoPyException}; use crate::function::{FuncArgs, KwArgs, OptionalArg}; +use crate::py_io; use crate::pyobject::{ BorrowValue, Either, IdProtocol, ItemProtocol, PyCallable, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, StaticType, TypeProtocol, }; use crate::slots::{SlotGetattro, SlotSetattro}; -use crate::vm::VirtualMachine; +use crate::VirtualMachine; use parking_lot::{ lock_api::{RawMutex as RawMutexT, RawMutexTimed, RawReentrantMutex}, @@ -255,12 +256,12 @@ fn run_thread(func: PyCallable, args: FuncArgs, vm: &VirtualMachine) { if let Err(exc) = func.invoke(args, vm) { // TODO: sys.unraisablehook let stderr = std::io::stderr(); - let mut stderr = stderr.lock(); + let mut stderr = py_io::IoWriter(stderr.lock()); let repr = vm.to_repr(&func.into_object()).ok(); let repr = repr .as_ref() .map_or("", |s| s.borrow_value()); - writeln!(stderr, "Exception ignored in thread started by: {}", repr) + writeln!(*stderr, "Exception ignored in thread started by: {}", repr) .and_then(|()| exceptions::write_exception(&mut stderr, vm, &exc)) .ok(); } diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 9acf5e817..fc7a6d242 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -782,9 +782,9 @@ impl VirtualMachine { #[wasm_bindgen(js_namespace = console)] fn error(s: &str); } - let mut s = Vec::::new(); + let mut s = String::new(); exceptions::write_exception(&mut s, self, &exc).unwrap(); - error(std::str::from_utf8(&s).unwrap()); + error(&s); panic!("{}; exception backtrace above", msg) } }