diff --git a/tests/snippets/stdlib_subprocess.py b/tests/snippets/stdlib_subprocess.py index 7721a1ac3..f1795f7fe 100644 --- a/tests/snippets/stdlib_subprocess.py +++ b/tests/snippets/stdlib_subprocess.py @@ -1,6 +1,8 @@ import subprocess import time +from testutils import assertRaises + p = subprocess.Popen(["echo", "test"]) time.sleep(0.1) @@ -9,3 +11,14 @@ assert p.returncode is None assert p.poll() == 0 assert p.returncode == 0 + +p = subprocess.Popen(["sleep", "2"]) + +assert p.poll() is None + +with assertRaises(subprocess.TimeoutExpired): + assert p.wait(1) + +p.wait() + +assert p.returncode == 0 diff --git a/vm/src/stdlib/subprocess.rs b/vm/src/stdlib/subprocess.rs index 97be50833..cdda8b16d 100644 --- a/vm/src/stdlib/subprocess.rs +++ b/vm/src/stdlib/subprocess.rs @@ -3,6 +3,7 @@ use std::time::Duration; use subprocess; +use crate::function::OptionalArg; use crate::obj::objlist::PyListRef; use crate::obj::objsequence; use crate::obj::objstr::{self, PyStringRef}; @@ -68,8 +69,8 @@ impl PopenRef { self.process.borrow().exit_status() } - fn wait(self, timeout: Option, vm: &VirtualMachine) -> PyResult<()> { - let timeout = match timeout { + fn wait(self, timeout: OptionalArg, vm: &VirtualMachine) -> PyResult<()> { + let timeout = match timeout.into_option() { Some(timeout) => self .process .borrow_mut() @@ -78,7 +79,8 @@ impl PopenRef { } .map_err(|s| vm.new_os_error(format!("Could not start program: {}", s)))?; if timeout.is_none() { - Err(vm.new_os_error("Timeout".to_string())) + let timeout_expired = vm.class("subprocess", "TimeoutExpired"); + Err(vm.new_exception(timeout_expired, "Timeout".to_string())) } else { Ok(()) } @@ -88,6 +90,9 @@ impl PopenRef { pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let ctx = &vm.ctx; + let subprocess_error = ctx.new_class("SubprocessError", ctx.exceptions.exception_type.clone()); + let timeout_expired = ctx.new_class("TimeoutExpired", subprocess_error.clone()); + let popen = py_class!(ctx, "Popen", ctx.object(), { "__new__" => ctx.new_rustfunc(PopenRef::new), "poll" => ctx.new_rustfunc(PopenRef::poll), @@ -97,6 +102,8 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let module = py_module!(vm, "subprocess", { "Popen" => popen, + "SubprocessError" => subprocess_error, + "TimeoutExpired" => timeout_expired, }); module