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
2 changes: 0 additions & 2 deletions Lib/test/test_c_locale_coercion.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,6 @@ def setUpClass(cls):
if not AVAILABLE_TARGETS:
raise unittest.SkipTest("No C-with-UTF-8 locale available")

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_external_target_locale_configuration(self):

# Explicitly setting a target locale should give the same behaviour as
Expand Down
30 changes: 15 additions & 15 deletions Lib/test/test_sys.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import builtins
import codecs
# import _datetime # TODO: RUSTPYTHON
import gc
import io
import locale
Expand Down Expand Up @@ -210,7 +209,7 @@ class SysModuleTest(unittest.TestCase):
def tearDown(self):
test.support.reap_children()

@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON; latin-1 codec not registered
def test_exit(self):
# call with two arguments
self.assertRaises(TypeError, sys.exit, 42, 42)
Expand Down Expand Up @@ -352,7 +351,7 @@ def test_setrecursionlimit(self):
finally:
sys.setrecursionlimit(old_limit)

@unittest.skipIf(getattr(sys, '_rustpython_debugbuild', False), 'TODO: RUSTPYTHON; stack overflow on debug build')
@unittest.skipIf(getattr(sys, "_rustpython_debugbuild", False), "TODO: RUSTPYTHON; stack overflow on debug build")
def test_recursionlimit_recovery(self):
if hasattr(sys, 'gettrace') and sys.gettrace():
self.skipTest('fatal error if run with a trace function')
Expand Down Expand Up @@ -433,7 +432,6 @@ def test_getwindowsversion(self):
# still has 5 elements
maj, min, buildno, plat, csd = sys.getwindowsversion()

@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: module 'sys' has no attribute 'call_tracing'
def test_call_tracing(self):
self.assertRaises(TypeError, sys.call_tracing, type, 2)

Expand Down Expand Up @@ -499,8 +497,6 @@ def test_getframemodulename(self):
self.assertIsNone(sys._getframemodulename(i))

# sys._current_frames() is a CPython-only gimmick.
# XXX RUSTPYTHON: above comment is from original cpython test; not sure why the cpython_only decorator wasn't added
@test.support.cpython_only
@threading_helper.reap_threads
@threading_helper.requires_working_threading()
def test_current_frames(self):
Expand Down Expand Up @@ -568,7 +564,6 @@ def g456():
leave_g.set()
t.join()

@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: module 'sys' has no attribute '_current_exceptions'
@threading_helper.reap_threads
@threading_helper.requires_working_threading()
def test_current_exceptions(self):
Expand Down Expand Up @@ -856,7 +851,7 @@ def test_subinterp_intern_singleton(self):
'''))
self.assertTrue(sys._is_interned(s))

@unittest.expectedFailure # TODO: RUSTPYTHON; needs update for context_aware_warnings
@unittest.expectedFailure # TODO: RUSTPYTHON; needs update for context_aware_warnings
def test_sys_flags(self):
self.assertTrue(sys.flags)
attrs = ("debug",
Expand Down Expand Up @@ -897,7 +892,7 @@ def test_clear_type_cache(self):
r"sys\._clear_type_cache\(\) is deprecated.*"):
sys._clear_type_cache()

@unittest.skip('TODO: RUSTPYTHON; cp424 encoding not supported, causes panic')
@unittest.skip("TODO: RUSTPYTHON; cp424 encoding not supported, causes panic")
@force_not_colorized
@support.requires_subprocess()
def test_ioencoding(self):
Expand Down Expand Up @@ -1062,12 +1057,12 @@ def check_locale_surrogateescape(self, locale):
'stdout: surrogateescape\n'
'stderr: backslashreplace\n')

@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON; stderr: backslashreplace
@support.requires_subprocess()
def test_c_locale_surrogateescape(self):
self.check_locale_surrogateescape('C')

@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON; stderr: backslashreplace
@support.requires_subprocess()
def test_posix_locale_surrogateescape(self):
self.check_locale_surrogateescape('POSIX')
Expand Down Expand Up @@ -1192,7 +1187,6 @@ def __del__(self):
rc, stdout, stderr = assert_python_ok('-c', code)
self.assertEqual(stdout.rstrip(), b'True')

@unittest.expectedFailure # TODO: RUSTPYTHON; IndexError: list index out of range
def test_issue20602(self):
# sys.flags and sys.float_info were wiped during shutdown.
code = """if 1:
Expand Down Expand Up @@ -1225,7 +1219,7 @@ def __del__(self):
self.assertEqual(stdout.rstrip(), b"")
self.assertEqual(stderr.rstrip(), b"")

@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: module 'sys' has no attribute 'getandroidapilevel'
@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: module 'sys' has no attribute 'getandroidapilevel'
@unittest.skipUnless(sys.platform == "android", "Android only")
def test_getandroidapilevel(self):
level = sys.getandroidapilevel()
Expand Down Expand Up @@ -1494,6 +1488,7 @@ def hook_func(args):
def test_custom_unraisablehook_fail(self):
_testcapi = import_helper.import_module('_testcapi')
from _testcapi import err_writeunraisable

def hook_func(*args):
raise Exception("hook_func failed")

Expand Down Expand Up @@ -1742,7 +1737,12 @@ def delx(self): del self.__x
x = property(getx, setx, delx, "")
check(x, size('5Pi'))
# PyCapsule
check(_datetime.datetime_CAPI, size('6P'))
try:
import _datetime
except ModuleNotFoundError:
pass
else:
check(_datetime.datetime_CAPI, size('6P'))
# rangeiterator
check(iter(range(1)), size('3l'))
check(iter(range(2**65)), size('3P'))
Expand Down Expand Up @@ -2227,7 +2227,7 @@ def test_jit_is_enabled(self):
assert_python_ok("-c", script.format(enabled=False), PYTHON_JIT="0")
assert_python_ok("-c", script.format(enabled=available), PYTHON_JIT="1")

@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON; ---
def test_jit_is_active(self):
available = sys._jit.is_available()
script = textwrap.dedent(
Expand Down
5 changes: 1 addition & 4 deletions crates/vm/src/object/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1078,10 +1078,7 @@ impl PyObject {
Some(true) => Ok(()),
// we've been resurrected by __del__
Some(false) => Err(()),
None => {
warn!("couldn't run __del__ method for object");
Ok(())
}
None => Ok(()),
}
}

Expand Down
49 changes: 45 additions & 4 deletions crates/vm/src/stdlib/sys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ mod sys {
use crate::{
AsObject, PyObject, PyObjectRef, PyPayload, PyRef, PyRefExact, PyResult,
builtins::{
PyBaseExceptionRef, PyDictRef, PyFrozenSet, PyNamespace, PyStr, PyStrRef, PyTupleRef,
PyTypeRef,
PyBaseExceptionRef, PyDictRef, PyFrozenSet, PyNamespace, PyStr, PyStrRef, PyTuple,
PyTupleRef, PyTypeRef,
},
common::{
ascii,
Expand Down Expand Up @@ -789,8 +789,22 @@ mod sys {

#[pyfunction]
fn exit(code: OptionalArg<PyObjectRef>, vm: &VirtualMachine) -> PyResult {
let code = code.unwrap_or_none(vm);
Err(vm.new_exception(vm.ctx.exceptions.system_exit.to_owned(), vec![code]))
let status = code.unwrap_or_none(vm);
let args = if let Some(status_tuple) = status.downcast_ref::<PyTuple>() {
status_tuple.as_slice().to_vec()
} else {
vec![status]
};
let exc = vm.invoke_exception(vm.ctx.exceptions.system_exit.to_owned(), args)?;
Err(exc)
}

#[pyfunction]
fn call_tracing(func: PyObjectRef, args: PyTupleRef, vm: &VirtualMachine) -> PyResult {
// CPython temporarily enables tracing state around this call.
// RustPython does not currently model the full C-level tracing toggles,
// but call semantics (func(*args)) are matched.
func.call(PosArgs::new(args.as_slice().to_vec()), vm)
}

#[pyfunction]
Expand Down Expand Up @@ -1031,6 +1045,33 @@ mod sys {
Ok(dict)
}

/// Return a dictionary mapping each thread's identifier to its currently
/// active exception, or None if no exception is active.
#[cfg(feature = "threading")]
#[pyfunction]
fn _current_exceptions(vm: &VirtualMachine) -> PyResult<PyDictRef> {
use crate::AsObject;
use crate::vm::thread::get_all_current_exceptions;

let dict = vm.ctx.new_dict();
for (thread_id, exc) in get_all_current_exceptions(vm) {
let key = vm.ctx.new_int(thread_id);
let value = exc.map_or_else(|| vm.ctx.none(), |e| e.into());
dict.set_item(key.as_object(), value, vm)?;
}

Ok(dict)
}

#[cfg(not(feature = "threading"))]
#[pyfunction]
fn _current_exceptions(vm: &VirtualMachine) -> PyResult<PyDictRef> {
let dict = vm.ctx.new_dict();
let key = vm.ctx.new_int(0);
dict.set_item(key.as_object(), vm.topmost_exception().to_pyobject(vm), vm)?;
Ok(dict)
}

/// Stub for non-threading builds - returns empty dict
#[cfg(not(feature = "threading"))]
#[pyfunction]
Expand Down
18 changes: 16 additions & 2 deletions crates/vm/src/types/structseq.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::common::lock::LazyLock;
use crate::{
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, atomic_func,
builtins::{PyBaseExceptionRef, PyStrRef, PyTuple, PyTupleRef, PyType, PyTypeRef},
builtins::{PyBaseExceptionRef, PyStr, PyStrRef, PyTuple, PyTupleRef, PyType, PyTypeRef},
class::{PyClassImpl, StaticType},
function::{Either, FuncArgs, PyComparisonValue, PyMethodDef, PyMethodFlags},
iter::PyExactSizeIterator,
Expand Down Expand Up @@ -225,7 +225,21 @@ pub trait PyStructSequence: StaticType + PyClassImpl + Sized + 'static {
} else {
(String::new(), "...")
};
let repr_str = format!("{}({}{})", Self::TP_NAME, body, suffix);
// Build qualified name: if MODULE_NAME is already in TP_NAME, use it directly.
// Otherwise, check __module__ attribute (set by #[pymodule] at runtime).
let type_name = if Self::MODULE_NAME.is_some() {
alloc::borrow::Cow::Borrowed(Self::TP_NAME)
} else {
let typ = zelf.class();
match typ.get_attr(identifier!(vm.ctx, __module__)) {
Some(module) if module.downcastable::<PyStr>() => {
let module_str = module.downcast_ref::<PyStr>().unwrap();
alloc::borrow::Cow::Owned(format!("{}.{}", module_str.as_str(), Self::NAME))
}
_ => alloc::borrow::Cow::Borrowed(Self::TP_NAME),
}
};
let repr_str = format!("{}({}{})", type_name, body, suffix);
Ok(vm.ctx.new_str(repr_str))
}

Expand Down
7 changes: 6 additions & 1 deletion crates/vm/src/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,12 @@ impl VirtualMachine {
let errors = if fd == 2 {
Some("backslashreplace")
} else {
self.state.config.settings.stdio_errors.as_deref()
self.state
.config
.settings
.stdio_errors
.as_deref()
.or(Some("surrogateescape"))
};

let stdio = self.call_method(
Expand Down
Loading