Skip to content

Commit cb2be65

Browse files
committed
fix timeout
1 parent 9c29b0c commit cb2be65

10 files changed

Lines changed: 208 additions & 79 deletions

File tree

Lib/test/test_os.py

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,6 @@ def test_access(self):
187187
os.close(f)
188188
self.assertTrue(os.access(os_helper.TESTFN, os.W_OK))
189189

190-
@unittest.skipIf(sys.platform == 'win32', "TODO: RUSTPYTHON; BrokenPipeError: (32, 'The process cannot access the file because it is being used by another process. (os error 32)')")
191190
@unittest.skipIf(
192191
support.is_wasi, "WASI does not support dup."
193192
)
@@ -230,7 +229,6 @@ def test_read(self):
230229
self.assertEqual(type(s), bytes)
231230
self.assertEqual(s, b"spam")
232231

233-
@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: module 'os' has no attribute 'readinto'. Did you mean: 'readlink'?
234232
def test_readinto(self):
235233
with open(os_helper.TESTFN, "w+b") as fobj:
236234
fobj.write(b"spam")
@@ -262,7 +260,6 @@ def test_readinto(self):
262260
os.lseek(fd, 0, 0)
263261
self.assertEqual(os.readinto(fd, bytearray()), 0)
264262

265-
@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: module 'os' has no attribute 'readinto'. Did you mean: 'readlink'?
266263
@unittest.skipUnless(hasattr(os, 'get_blocking'),
267264
'needs os.get_blocking() and os.set_blocking()')
268265
@unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
@@ -294,7 +291,6 @@ def test_readinto_non_blocking(self):
294291
if w is not None:
295292
os.close(w)
296293

297-
@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: module 'os' has no attribute 'readinto'. Did you mean: 'readlink'?
298294
def test_readinto_badarg(self):
299295
with open(os_helper.TESTFN, "w+b") as fobj:
300296
fobj.write(b"spam")
@@ -1423,7 +1419,6 @@ def test_ror_operator(self):
14231419
self._test_underlying_process_env('_A_', '')
14241420
self._test_underlying_process_env(overridden_key, original_value)
14251421

1426-
@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: module 'os' has no attribute 'reload_environ'
14271422
def test_reload_environ(self):
14281423
# Test os.reload_environ()
14291424
has_environb = hasattr(os, 'environb')
@@ -1887,17 +1882,6 @@ def walk(self, top, **kwargs):
18871882
bdirs[:] = list(map(os.fsencode, dirs))
18881883
bfiles[:] = list(map(os.fsencode, files))
18891884

1890-
@unittest.expectedFailure # TODO: RUSTPYTHON; WalkTests doesn't have these methods
1891-
def test_compare_to_walk(self):
1892-
return super().test_compare_to_walk()
1893-
1894-
@unittest.expectedFailure # TODO: RUSTPYTHON; WalkTests doesn't have these methods
1895-
def test_dir_fd(self):
1896-
return super().test_dir_fd()
1897-
1898-
@unittest.expectedFailure # TODO: RUSTPYTHON; WalkTests doesn't have these methods
1899-
def test_yields_correct_dir_fd(self):
1900-
return super().test_yields_correct_dir_fd()
19011885

19021886
@unittest.skipUnless(hasattr(os, 'fwalk'), "Test needs os.fwalk()")
19031887
class BytesFwalkTests(FwalkTests):
@@ -2586,7 +2570,6 @@ def test_fpathconf_bad_fd(self):
25862570
self.check(os.pathconf, "PC_NAME_MAX")
25872571
self.check(os.fpathconf, "PC_NAME_MAX")
25882572

2589-
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: RuntimeWarning not raised
25902573
@unittest.skipUnless(hasattr(os, 'ftruncate'), 'test needs os.ftruncate()')
25912574
def test_ftruncate(self):
25922575
self.check(os.truncate, 0)
@@ -2633,13 +2616,6 @@ def test_blocking(self):
26332616
self.check(os.get_blocking)
26342617
self.check(os.set_blocking, True)
26352618

2636-
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: RuntimeWarning not raised
2637-
def test_fsync(self):
2638-
return super().test_fsync()
2639-
2640-
@unittest.expectedFailure # TODO: RUSTPYTHON; NotADirectoryError: [Errno 20] Not a directory
2641-
def test_fchdir(self):
2642-
return super().test_fchdir()
26432619

26442620

26452621

@@ -3709,7 +3685,6 @@ def test_nowait(self):
37093685
pid = os.spawnv(os.P_NOWAIT, program, args)
37103686
support.wait_process(pid, exitcode=self.exitcode)
37113687

3712-
@unittest.expectedFailure # TODO: RUSTPYTHON; fix spawnv bytes
37133688
@requires_os_func('spawnve')
37143689
def test_spawnve_bytes(self):
37153690
# Test bytes handling in parse_arglist and parse_envlist (#28114)
@@ -5423,7 +5398,6 @@ def test_context_manager_exception(self):
54235398
with self.check_no_resource_warning():
54245399
del iterator
54255400

5426-
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: ResourceWarning not triggered
54275401
def test_resource_warning(self):
54285402
self.create_file("file.txt")
54295403
self.create_file("file2.txt")

Lib/test/test_posix.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,6 @@ def test_confstr(self):
583583
self.assertGreater(len(path), 0)
584584
self.assertEqual(posix.confstr(posix.confstr_names["CS_PATH"]), path)
585585

586-
@unittest.expectedFailureIf(sys.platform in ("darwin", "linux"), "TODO: RUSTPYTHON; AssertionError: \"configuration names must be strings or integers\" does not match \"Expected type 'str' but 'float' found.\"")
587586
@unittest.skipUnless(hasattr(posix, 'sysconf'),
588587
'test needs posix.sysconf()')
589588
def test_sysconf(self):
@@ -1623,7 +1622,6 @@ def test_chown_dir_fd(self):
16231622
with self.prepare_file() as (dir_fd, name, fullname):
16241623
posix.chown(name, os.getuid(), os.getgid(), dir_fd=dir_fd)
16251624

1626-
@unittest.expectedFailureIf(sys.platform in ("darwin", "linux"), "TODO: RUSTPYTHON; AssertionError: RuntimeWarning not triggered")
16271625
@unittest.skipUnless(os.stat in os.supports_dir_fd, "test needs dir_fd support in os.stat()")
16281626
def test_stat_dir_fd(self):
16291627
with self.prepare() as (dir_fd, name, fullname):

Lib/test/test_signal.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,6 @@ def test_valid_signals(self):
192192
self.assertNotIn(signal.NSIG, s)
193193
self.assertLess(len(s), signal.NSIG)
194194

195-
@unittest.expectedFailure # TODO: RUSTPYTHON
196195
def test_issue9324(self):
197196
# Updated for issue #10003, adding SIGBREAK
198197
handler = lambda x, y: None
@@ -1414,7 +1413,6 @@ def test_sigint(self):
14141413
with self.assertRaises(KeyboardInterrupt):
14151414
signal.raise_signal(signal.SIGINT)
14161415

1417-
@unittest.expectedFailure # TODO: RUSTPYTHON
14181416
@unittest.skipIf(sys.platform != "win32", "Windows specific test")
14191417
def test_invalid_argument(self):
14201418
try:

Lib/test/test_subprocess.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,6 @@ def test_env(self):
800800
stdout, stderr = p.communicate()
801801
self.assertEqual(stdout, b"orange")
802802

803-
@unittest.expectedFailure # TODO: RUSTPYTHON
804803
@unittest.skipUnless(sys.platform == "win32", "Windows only issue")
805804
def test_win32_duplicate_envs(self):
806805
newenv = os.environ.copy()

crates/stdlib/src/socket.rs

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ mod _socket {
1616
common::os::ErrorExt,
1717
convert::{IntoPyException, ToPyObject, TryFromBorrowedObject, TryFromObject},
1818
function::{
19-
ArgBytesLike, ArgMemoryBuffer, ArgStrOrBytesLike, Either, FsPath, OptionalArg,
20-
OptionalOption,
19+
ArgBytesLike, ArgIntoFloat, ArgMemoryBuffer, ArgStrOrBytesLike, Either, FsPath,
20+
OptionalArg, OptionalOption,
2121
},
2222
types::{Constructor, DefaultConstructor, Initializer, Representable},
2323
utils::ToCString,
@@ -2201,12 +2201,29 @@ mod _socket {
22012201
}
22022202

22032203
#[pymethod]
2204-
fn settimeout(&self, timeout: Option<Duration>) -> io::Result<()> {
2205-
self.timeout
2206-
.store(timeout.map_or(-1.0, |d| d.as_secs_f64()));
2204+
fn settimeout(&self, timeout: Option<ArgIntoFloat>, vm: &VirtualMachine) -> PyResult<()> {
2205+
let timeout = match timeout {
2206+
Some(t) => {
2207+
let f = t.into_float();
2208+
if f.is_nan() {
2209+
return Err(vm.new_value_error(
2210+
"Invalid value NaN (not a number)".to_owned(),
2211+
));
2212+
}
2213+
if f < 0.0 || !f.is_finite() {
2214+
return Err(vm.new_value_error("Timeout value out of range".to_owned()));
2215+
}
2216+
Some(f)
2217+
}
2218+
None => None,
2219+
};
2220+
self.timeout.store(timeout.unwrap_or(-1.0));
22072221
// even if timeout is > 0 the socket needs to be nonblocking in order for us to select() on
22082222
// it
2209-
self.sock()?.set_nonblocking(timeout.is_some())
2223+
self.sock()
2224+
.map_err(|e| e.into_pyexception(vm))?
2225+
.set_nonblocking(timeout.is_some())
2226+
.map_err(|e| e.into_pyexception(vm))
22102227
}
22112228

22122229
#[pymethod]
@@ -3366,8 +3383,24 @@ mod _socket {
33663383
}
33673384

33683385
#[pyfunction]
3369-
fn setdefaulttimeout(timeout: Option<Duration>) {
3370-
DEFAULT_TIMEOUT.store(timeout.map_or(-1.0, |d| d.as_secs_f64()));
3386+
fn setdefaulttimeout(timeout: Option<ArgIntoFloat>, vm: &VirtualMachine) -> PyResult<()> {
3387+
let val = match timeout {
3388+
Some(t) => {
3389+
let f = t.into_float();
3390+
if f.is_nan() {
3391+
return Err(vm.new_value_error(
3392+
"Invalid value NaN (not a number)".to_owned(),
3393+
));
3394+
}
3395+
if f < 0.0 || !f.is_finite() {
3396+
return Err(vm.new_value_error("Timeout value out of range".to_owned()));
3397+
}
3398+
f
3399+
}
3400+
None => -1.0,
3401+
};
3402+
DEFAULT_TIMEOUT.store(val);
3403+
Ok(())
33713404
}
33723405

33733406
#[pyfunction]

crates/vm/src/stdlib/nt.rs

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,18 @@ pub(crate) mod module {
183183
environ
184184
}
185185

186+
#[pyfunction]
187+
fn _create_environ(vm: &VirtualMachine) -> PyDictRef {
188+
let environ = vm.ctx.new_dict();
189+
for (key, value) in env::vars() {
190+
if key.starts_with('=') {
191+
continue;
192+
}
193+
environ.set_item(&key, vm.new_pyobj(value), vm).unwrap();
194+
}
195+
environ
196+
}
197+
186198
#[derive(FromArgs)]
187199
struct ChmodArgs<'a> {
188200
#[pyarg(any)]
@@ -903,16 +915,14 @@ pub(crate) mod module {
903915
argv: Either<PyListRef, PyTupleRef>,
904916
vm: &VirtualMachine,
905917
) -> PyResult<intptr_t> {
918+
use crate::function::FsPath;
906919
use std::iter::once;
907920

908-
let make_widestring =
909-
|s: &str| widestring::WideCString::from_os_str(s).map_err(|err| err.to_pyexception(vm));
910-
911921
let path = path.to_wide_cstring(vm)?;
912922

913923
let argv = vm.extract_elements_with(argv.as_ref(), |obj| {
914-
let arg = PyStrRef::try_from_object(vm, obj)?;
915-
make_widestring(arg.as_str())
924+
let fspath = FsPath::try_from_path_like(obj, true, vm)?;
925+
fspath.to_wide_cstring(vm)
916926
})?;
917927

918928
let first = argv
@@ -946,16 +956,14 @@ pub(crate) mod module {
946956
env: PyDictRef,
947957
vm: &VirtualMachine,
948958
) -> PyResult<intptr_t> {
959+
use crate::function::FsPath;
949960
use std::iter::once;
950961

951-
let make_widestring =
952-
|s: &str| widestring::WideCString::from_os_str(s).map_err(|err| err.to_pyexception(vm));
953-
954962
let path = path.to_wide_cstring(vm)?;
955963

956964
let argv = vm.extract_elements_with(argv.as_ref(), |obj| {
957-
let arg = PyStrRef::try_from_object(vm, obj)?;
958-
make_widestring(arg.as_str())
965+
let fspath = FsPath::try_from_path_like(obj, true, vm)?;
966+
fspath.to_wide_cstring(vm)
959967
})?;
960968

961969
let first = argv
@@ -975,23 +983,22 @@ pub(crate) mod module {
975983
// Build environment strings as "KEY=VALUE\0" wide strings
976984
let mut env_strings: Vec<widestring::WideCString> = Vec::new();
977985
for (key, value) in env.into_iter() {
978-
let key = PyStrRef::try_from_object(vm, key)?;
979-
let value = PyStrRef::try_from_object(vm, value)?;
980-
let key_str = key.as_str();
981-
let value_str = value.as_str();
986+
let key = FsPath::try_from_path_like(key, true, vm)?;
987+
let value = FsPath::try_from_path_like(value, true, vm)?;
988+
let key_str = key.to_string_lossy();
989+
let value_str = value.to_string_lossy();
982990

983-
// Validate: no null characters in key or value
984-
if key_str.contains('\0') || value_str.contains('\0') {
985-
return Err(vm.new_value_error("embedded null character"));
986-
}
987991
// Validate: no '=' in key (search from index 1 because on Windows
988992
// starting '=' is allowed for defining hidden environment variables)
989993
if key_str.get(1..).is_some_and(|s| s.contains('=')) {
990994
return Err(vm.new_value_error("illegal environment variable name"));
991995
}
992996

993997
let env_str = format!("{}={}", key_str, value_str);
994-
env_strings.push(make_widestring(&env_str)?);
998+
env_strings.push(
999+
widestring::WideCString::from_os_str(&*std::ffi::OsString::from(env_str))
1000+
.map_err(|err| err.to_pyexception(vm))?,
1001+
);
9951002
}
9961003

9971004
let envp: Vec<*const u16> = env_strings

0 commit comments

Comments
 (0)