Skip to content

Commit 019036d

Browse files
authored
Merge pull request RustPython#1767 from RustPython/coolreader18/windows-fd-from-handle
Fix writing to stdio streams on Windows
2 parents 239e018 + 6b580c5 commit 019036d

File tree

8 files changed

+51
-26
lines changed

8 files changed

+51
-26
lines changed

Lib/_sitebuiltins.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,8 @@
88
# Note this means this module should also avoid keep things alive in its
99
# globals.
1010

11-
import os
1211
import sys
1312

14-
sys.stdin = sys.__stdin__ = getattr(sys, '__stdin__', False) or os.fdopen(0, "r")
15-
sys.stdout = sys.__stdout__ = getattr(sys, '__stdout__', False) or os.fdopen(1, "w")
16-
sys.stderr = sys.__stderr__ = getattr(sys, '__stderr__', False) or os.fdopen(2, "w")
17-
1813

1914
class Quitter(object):
2015
def __init__(self, name, eof):

Lib/platform.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -281,9 +281,10 @@ def _syscmd_ver(system='', release='', version='',
281281
for cmd in ('ver', 'command /c ver', 'cmd /c ver'):
282282
try:
283283
info = subprocess.check_output(cmd,
284-
stderr=subprocess.DEVNULL,
285-
text=True,
286-
shell=True)
284+
stderr=subprocess.DEVNULL,)
285+
# XXX RustPython TODO: more Popen args
286+
# text=True,
287+
# shell=True)
287288
except (OSError, subprocess.CalledProcessError) as why:
288289
#print('Command %s failed: %s' % (cmd, why))
289290
continue

Lib/test/list_tests.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def test_repr(self):
6767
self.assertEqual(repr(a2), "[0, 1, 2, [...], 3]")
6868

6969
# TODO: RUSTPYTHON
70-
@unittest.expectedFailure
70+
@unittest.skip("TODO: RUSTPYTHON")
7171
def test_repr_deep(self):
7272
a = self.type2test([])
7373
for i in range(sys.getrecursionlimit() + 100):

Lib/test/test_dict.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ def __repr__(self):
558558
self.assertRaises(Exc, repr, d)
559559

560560
# TODO: RUSTPYTHON
561-
@unittest.expectedFailure
561+
@unittest.skip("TODO: RUSTPYTHON")
562562
def test_repr_deep(self):
563563
d = {}
564564
for i in range(sys.getrecursionlimit() + 100):

vm/src/builtins.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ use crate::pyobject::{
3232
};
3333
use crate::scope::Scope;
3434
use crate::stdlib::ast;
35-
#[cfg(not(target_arch = "wasm32"))]
36-
use crate::stdlib::io::io_open;
3735
use crate::vm::VirtualMachine;
3836

3937
fn builtin_abs(x: PyObjectRef, vm: &VirtualMachine) -> PyResult {
@@ -757,11 +755,6 @@ fn builtin_vars(obj: OptionalArg, vm: &VirtualMachine) -> PyResult {
757755
pub fn make_module(vm: &VirtualMachine, module: PyObjectRef) {
758756
let ctx = &vm.ctx;
759757

760-
#[cfg(target_arch = "wasm32")]
761-
let open = vm.ctx.none();
762-
#[cfg(not(target_arch = "wasm32"))]
763-
let open = vm.ctx.new_function(io_open);
764-
765758
#[cfg(feature = "rustpython-compiler")]
766759
{
767760
extend_module!(vm, module, {
@@ -817,7 +810,6 @@ pub fn make_module(vm: &VirtualMachine, module: PyObjectRef) {
817810
"min" => ctx.new_function(builtin_min),
818811
"object" => ctx.object(),
819812
"oct" => ctx.new_function(builtin_oct),
820-
"open" => open,
821813
"ord" => ctx.new_function(builtin_ord),
822814
"next" => ctx.new_function(builtin_next),
823815
"pow" => ctx.new_function(builtin_pow),

vm/src/stdlib/os.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,17 @@ pub fn raw_file_number(handle: File) -> i64 {
7070

7171
#[cfg(windows)]
7272
pub fn rust_file(raw_fileno: i64) -> File {
73-
use std::os::windows::io::FromRawHandle;
73+
use std::os::windows::io::{AsRawHandle, FromRawHandle, RawHandle};
74+
75+
let raw_fileno = match raw_fileno {
76+
0 => io::stdin().as_raw_handle(),
77+
1 => io::stdout().as_raw_handle(),
78+
2 => io::stderr().as_raw_handle(),
79+
fno => fno as RawHandle,
80+
};
7481

7582
//This seems to work as expected but further testing is required.
76-
unsafe { File::from_raw_handle(raw_fileno as *mut ffi::c_void) }
83+
unsafe { File::from_raw_handle(raw_fileno) }
7784
}
7885

7986
#[cfg(all(not(unix), not(windows)))]

vm/src/stdlib/subprocess.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
248248

249249
let subprocess_error = ctx.new_class("SubprocessError", ctx.exceptions.exception_type.clone());
250250
let timeout_expired = ctx.new_class("TimeoutExpired", subprocess_error.clone());
251+
let called_process_error = ctx.new_class("CalledProcessError", subprocess_error.clone());
251252

252253
let popen = py_class!(ctx, "Popen", ctx.object(), {
253254
(slot new) => PopenRef::new,
@@ -270,6 +271,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
270271
"Popen" => popen,
271272
"SubprocessError" => subprocess_error,
272273
"TimeoutExpired" => timeout_expired,
274+
"CalledProcessError" => called_process_error,
273275
"PIPE" => ctx.new_int(-1),
274276
"STDOUT" => ctx.new_int(-2),
275277
"DEVNULL" => ctx.new_int(-3),

vm/src/vm.rs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -231,13 +231,41 @@ impl VirtualMachine {
231231
builtins::make_module(self, self.builtins.clone());
232232
sysmodule::make_module(self, self.sys_module.clone(), self.builtins.clone());
233233

234-
#[cfg(not(target_arch = "wasm32"))]
235-
import::import_builtin(self, "signal").expect("Couldn't initialize signal module");
234+
let inner_init = || -> PyResult<()> {
235+
#[cfg(not(target_arch = "wasm32"))]
236+
import::import_builtin(self, "signal")?;
237+
238+
import::init_importlib(self, initialize_parameter)?;
239+
240+
#[cfg(not(target_arch = "wasm32"))]
241+
{
242+
let io = self.import("io", &[], 0)?;
243+
let io_open = self.get_attribute(io.clone(), "open")?;
244+
let set_stdio = |name, fd, mode: &str| {
245+
let stdio = self.invoke(
246+
&io_open,
247+
vec![self.new_int(fd), self.new_str(mode.to_owned())],
248+
)?;
249+
self.set_attr(
250+
&self.sys_module,
251+
format!("__{}__", name), // e.g. __stdin__
252+
stdio.clone(),
253+
)?;
254+
self.set_attr(&self.sys_module, name, stdio)?;
255+
Ok(())
256+
};
257+
set_stdio("stdin", 0, "r")?;
258+
set_stdio("stdout", 1, "w")?;
259+
set_stdio("stderr", 2, "w")?;
260+
261+
let open_wrapper = self.get_attribute(io, "OpenWrapper")?;
262+
self.set_attr(&self.builtins, "open", open_wrapper)?;
263+
}
264+
265+
Ok(())
266+
};
236267

237-
self.expect_pyresult(
238-
import::init_importlib(self, initialize_parameter),
239-
"Initialize importlib fail",
240-
);
268+
self.expect_pyresult(inner_init(), "initializiation failed");
241269

242270
self.initialized = true;
243271
}

0 commit comments

Comments
 (0)