From 70d9e43104a5d11c69226a7c996f3d5817b53180 Mon Sep 17 00:00:00 2001 From: lynskylate Date: Tue, 20 Aug 2019 01:18:34 +0800 Subject: [PATCH 1/6] Add settimeout and setblocking for socket module --- tests/snippets/stdlib_socket.py | 21 +++++++ vm/src/stdlib/socket.rs | 103 ++++++++++++++++++++++++++++++-- 2 files changed, 119 insertions(+), 5 deletions(-) diff --git a/tests/snippets/stdlib_socket.py b/tests/snippets/stdlib_socket.py index d5727bb25..2370fc9ed 100644 --- a/tests/snippets/stdlib_socket.py +++ b/tests/snippets/stdlib_socket.py @@ -137,3 +137,24 @@ with assertRaises(OSError): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: pass + +connector = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +connection.settimeout(None) +assert connection.getblocking() == True +assert connection.gettimeout() == None + +connection.settimeout(0) +assert connection.getblocking() == False +assert connection.gettimeout() == 0 + +connection.setblocking(True) +assert connection.getblocking() == True +assert connection.gettimeout() == None + +connection.setblocking(False) +assert connection.getblocking() == False +assert connection.gettimeout() == 0.0 + +connection.settimeout(3) +assert connection.gettimeout() == 3 +assert connection.getblocking() == True \ No newline at end of file diff --git a/vm/src/stdlib/socket.rs b/vm/src/stdlib/socket.rs index c83b75656..71ebc62ac 100644 --- a/vm/src/stdlib/socket.rs +++ b/vm/src/stdlib/socket.rs @@ -3,6 +3,7 @@ use std::io; use std::io::Read; use std::io::Write; use std::net::{Ipv4Addr, SocketAddr, TcpListener, TcpStream, ToSocketAddrs, UdpSocket}; +use std::time::Duration; #[cfg(all(unix, not(target_os = "redox")))] use nix::unistd::sethostname; @@ -12,11 +13,13 @@ use gethostname::gethostname; use byteorder::{BigEndian, ByteOrder}; use crate::function::PyFuncArgs; +use crate::obj::objbool::boolval; use crate::obj::objbytes::PyBytesRef; +use crate::obj::objfloat::try_float; use crate::obj::objint::PyIntRef; use crate::obj::objstr::PyStringRef; use crate::obj::objtuple::PyTupleRef; -use crate::pyobject::{PyObjectRef, PyRef, PyResult, PyValue, TryFromObject}; +use crate::pyobject::{PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol}; use crate::vm::VirtualMachine; use crate::obj::objtype::PyClassRef; @@ -152,6 +155,7 @@ pub struct Socket { address_family: AddressFamily, socket_kind: SocketKind, con: RefCell>, + timeout: RefCell>, } impl PyValue for Socket { @@ -166,6 +170,7 @@ impl Socket { address_family, socket_kind, con: RefCell::new(None), + timeout: RefCell::new(None), } } } @@ -193,7 +198,7 @@ impl SocketRef { fn connect(self, address: Address, vm: &VirtualMachine) -> PyResult<()> { let address_string = address.get_address_string(); - match self.socket_kind { + let res = match self.socket_kind { SocketKind::Stream => match TcpStream::connect(address_string) { Ok(stream) => { self.con.borrow_mut().replace(Connection::TcpStream(stream)); @@ -211,13 +216,15 @@ impl SocketRef { Err(vm.new_type_error("".to_string())) } } - } + }; + self.internal_setblocking(self.internal_getblocking()); + return res; } fn bind(self, address: Address, vm: &VirtualMachine) -> PyResult<()> { let address_string = address.get_address_string(); - match self.socket_kind { + let res = match self.socket_kind { SocketKind::Stream => match TcpListener::bind(address_string) { Ok(stream) => { self.con @@ -234,7 +241,9 @@ impl SocketRef { } Err(s) => Err(vm.new_os_error(s.to_string())), }, - } + }; + self.internal_setblocking(self.internal_getblocking()); + return res; } fn listen(self, _num: PyIntRef, _vm: &VirtualMachine) {} @@ -254,6 +263,7 @@ impl SocketRef { address_family: self.address_family, socket_kind: self.socket_kind, con: RefCell::new(Some(Connection::TcpStream(tcp_stream))), + timeout: RefCell::new(None), } .into_ref(vm); @@ -352,6 +362,85 @@ impl SocketRef { Err(s) => Err(vm.new_os_error(s.to_string())), } } + + fn gettimeout(self, vm: &VirtualMachine) -> PyResult { + match self.timeout.borrow().as_ref() { + Some(duration) => Ok(vm.ctx.new_float(duration.as_secs() as f64)), + None => Ok(vm.get_none()), + } + } + + fn setblocking(self, block: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { + match boolval(vm, block.clone()) { + Ok(value) => { + if value { + self.timeout.replace(None); + } else { + self.timeout.borrow_mut().replace(Duration::from_secs(0)); + } + if self.internal_setblocking(value) { + Ok(()) + } else { + Err(vm.new_os_error("Set socket blocking error".to_string())) + } + } + Err(_) => Err(vm.new_type_error(format!( + "an integer os required (got type {})", + &block.class().name.clone() + ))), + } + } + + fn internal_setblocking(&self, block: bool) -> bool { + match self.con.borrow_mut().as_mut() { + Some(conn) => match conn { + Connection::TcpStream(con) => con.set_nonblocking(!block).is_ok(), + Connection::TcpListener(con) => con.set_nonblocking(!block).is_ok(), + Connection::UdpSocket(con) => con.set_nonblocking(!block).is_ok(), + }, + None => true, + } + } + + fn getblocking(self, vm: &VirtualMachine) -> PyResult { + Ok(vm.ctx.new_bool(self.internal_getblocking())) + } + + fn internal_getblocking(&self) -> bool { + match self.timeout.borrow().as_ref() { + Some(duration) => { + if duration.as_secs() != 0 { + true + } else { + false + } + } + None => true, + } + } + + fn settimeout(self, timeout: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { + if vm.is_none(&timeout) { + return self.setblocking(vm.new_bool(true), vm); + } + match try_float(&timeout, vm) { + Ok(option_timeout) => { + let timeout = option_timeout.unwrap_or(0.0); + self.timeout + .borrow_mut() + .replace(Duration::from_secs(timeout as u64)); + + let block = timeout <= 0.0; + + self.internal_setblocking(block); + Ok(()) + } + Err(_) => Err(vm.new_type_error(format!( + "an integer required (got {} object)", + &timeout.class().name.clone() + ))), + } + } } struct Address { @@ -448,6 +537,10 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { "sendto" => ctx.new_rustfunc(SocketRef::sendto), "recvfrom" => ctx.new_rustfunc(SocketRef::recvfrom), "fileno" => ctx.new_rustfunc(SocketRef::fileno), + "gettimeout" => ctx.new_rustfunc(SocketRef::gettimeout), + "settimeout" => ctx.new_rustfunc(SocketRef::settimeout), + "getblocking" => ctx.new_rustfunc(SocketRef::getblocking), + "setblocking" => ctx.new_rustfunc(SocketRef::setblocking), }); let module = py_module!(vm, "socket", { From a8c295936f009b32ad6b50b2e46464d2a2902c7e Mon Sep 17 00:00:00 2001 From: lynskylate Date: Sun, 25 Aug 2019 15:01:15 +0800 Subject: [PATCH 2/6] Refactor code --- vm/src/obj/objfloat.rs | 11 ++- vm/src/stdlib/socket.rs | 173 ++++++++++++++++++++++++---------------- 2 files changed, 116 insertions(+), 68 deletions(-) diff --git a/vm/src/obj/objfloat.rs b/vm/src/obj/objfloat.rs index b0dbaebe2..c38fc7041 100644 --- a/vm/src/obj/objfloat.rs +++ b/vm/src/obj/objfloat.rs @@ -8,7 +8,7 @@ use crate::obj::objtype::PyClassRef; use crate::pyhash; use crate::pyobject::{ IdProtocol, IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, - TypeProtocol, + TryFromObject, TypeProtocol, }; use crate::vm::VirtualMachine; use hexf_parse; @@ -41,6 +41,15 @@ impl IntoPyObject for f64 { } } +impl TryFromObject for f64 { + fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { + try_float(&obj, vm)?.map_or_else( + || Err(vm.new_type_error(format!("Expect float object, but get {}", obj.class().name))), + |val| Ok(val), + ) + } +} + impl From for PyFloat { fn from(value: f64) -> Self { PyFloat { value } diff --git a/vm/src/stdlib/socket.rs b/vm/src/stdlib/socket.rs index 71ebc62ac..a3dc9490a 100644 --- a/vm/src/stdlib/socket.rs +++ b/vm/src/stdlib/socket.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; use std::io; use std::io::Read; use std::io::Write; -use std::net::{Ipv4Addr, SocketAddr, TcpListener, TcpStream, ToSocketAddrs, UdpSocket}; +use std::net::{Ipv4Addr, SocketAddr, TcpListener, TcpStream, ToSocketAddrs, UdpSocket }; use std::time::Duration; #[cfg(all(unix, not(target_os = "redox")))] @@ -12,10 +12,8 @@ use gethostname::gethostname; use byteorder::{BigEndian, ByteOrder}; -use crate::function::PyFuncArgs; -use crate::obj::objbool::boolval; +use crate::function::{OptionalArg, PyFuncArgs}; use crate::obj::objbytes::PyBytesRef; -use crate::obj::objfloat::try_float; use crate::obj::objint::PyIntRef; use crate::obj::objstr::PyStringRef; use crate::obj::objtuple::PyTupleRef; @@ -27,6 +25,7 @@ use crate::obj::objtype::PyClassRef; use crate::stdlib::os::convert_nix_error; use num_bigint::Sign; use num_traits::ToPrimitive; +use itertools::Itertools; #[derive(Debug, Copy, Clone)] enum AddressFamily { @@ -125,6 +124,27 @@ impl Connection { fn fileno(&self) -> i64 { unimplemented!(); } + + fn setblocking(&mut self, value: bool) -> io::Result<()> { + match self { + Connection::TcpListener(con) => con.set_nonblocking(!value), + Connection::UdpSocket(con) => con.set_nonblocking(!value), + Connection::TcpStream(con) => con.set_nonblocking(!value), + } + } + + fn settimeout(&mut self, duration: Duration) -> io::Result<()> { + match self { + // net + Connection::TcpListener(_con) => Ok(()), + Connection::UdpSocket(con) => con + .set_read_timeout(Some(duration)) + .and_then(|_| con.set_write_timeout(Some(duration))), + Connection::TcpStream(con) => con + .set_read_timeout(Some(duration)) + .and_then(|_| con.set_write_timeout(Some(duration))), + } + } } impl Read for Connection { @@ -198,14 +218,39 @@ impl SocketRef { fn connect(self, address: Address, vm: &VirtualMachine) -> PyResult<()> { let address_string = address.get_address_string(); - let res = match self.socket_kind { - SocketKind::Stream => match TcpStream::connect(address_string) { - Ok(stream) => { - self.con.borrow_mut().replace(Connection::TcpStream(stream)); - Ok(()) + match self.socket_kind { + SocketKind::Stream => { + let con = if let Some(duration) = self.timeout.borrow().as_ref() { + let sock_addr = match address_string.to_socket_addrs() { + Ok(mut sock_addrs) => { + if sock_addrs.len() == 0 { + let error_type = vm.class("socket", "gaierror"); + return Err(vm.new_exception(error_type, "nodename nor servname provided, or not known".to_string())) + }else{ + sock_addrs.next().unwrap() + } + } + Err(e) => { + let error_type = vm.class("socket", "gaierror"); + return Err(vm.new_exception(error_type, e.to_string())); + } + }; + TcpStream::connect_timeout(&sock_addr, duration.clone()) + } else { + TcpStream::connect(address_string) + }; + match con { + Ok(stream) => { + self.con.borrow_mut().replace(Connection::TcpStream(stream)); + Ok(()) + } + Err(ref e) if e.kind() == io::ErrorKind::TimedOut => { + let socket_timeout = vm.class("socket", "timeout"); + Err(vm.new_exception(socket_timeout, "Timed out".to_string())) + } + Err(s) => Err(vm.new_os_error(s.to_string())), } - Err(s) => Err(vm.new_os_error(s.to_string())), - }, + } SocketKind::Dgram => { if let Some(Connection::UdpSocket(con)) = self.con.borrow().as_ref() { match con.connect(address_string) { @@ -216,15 +261,13 @@ impl SocketRef { Err(vm.new_type_error("".to_string())) } } - }; - self.internal_setblocking(self.internal_getblocking()); - return res; + } } fn bind(self, address: Address, vm: &VirtualMachine) -> PyResult<()> { let address_string = address.get_address_string(); - let res = match self.socket_kind { + match self.socket_kind { SocketKind::Stream => match TcpListener::bind(address_string) { Ok(stream) => { self.con @@ -241,9 +284,7 @@ impl SocketRef { } Err(s) => Err(vm.new_os_error(s.to_string())), }, - }; - self.internal_setblocking(self.internal_getblocking()); - return res; + } } fn listen(self, _num: PyIntRef, _vm: &VirtualMachine) {} @@ -277,6 +318,10 @@ impl SocketRef { match self.con.borrow_mut().as_mut() { Some(v) => match v.read_exact(&mut buffer) { Ok(_) => (), + Err(ref e) if e.kind() == io::ErrorKind::TimedOut => { + let socket_timeout = vm.class("socket", "timeout"); + return Err(vm.new_exception(socket_timeout, "Timed out".to_string())); + } Err(s) => return Err(vm.new_os_error(s.to_string())), }, None => return Err(vm.new_type_error("".to_string())), @@ -305,9 +350,13 @@ impl SocketRef { match self.con.borrow_mut().as_mut() { Some(v) => match v.write(&bytes) { Ok(_) => (), + Err(ref e) if e.kind() == io::ErrorKind::TimedOut => { + let socket_timeout = vm.class("socket", "timeout"); + return Err(vm.new_exception(socket_timeout, "Timed out".to_string())); + } Err(s) => return Err(vm.new_os_error(s.to_string())), }, - None => return Err(vm.new_type_error("".to_string())), + None => return Err(vm.new_type_error("Socket is not connected".to_string())), }; Ok(()) } @@ -363,82 +412,68 @@ impl SocketRef { } } - fn gettimeout(self, vm: &VirtualMachine) -> PyResult { + fn gettimeout(self, _vm: &VirtualMachine) -> PyResult> { match self.timeout.borrow().as_ref() { - Some(duration) => Ok(vm.ctx.new_float(duration.as_secs() as f64)), - None => Ok(vm.get_none()), + Some(duration) => Ok(Some(duration.as_secs() as f64)), + None => Ok(None), } } - fn setblocking(self, block: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { - match boolval(vm, block.clone()) { - Ok(value) => { + fn setblocking(self, block: OptionalArg, vm: &VirtualMachine) -> PyResult<()> { + match block { + OptionalArg::Present(value) => { if value { self.timeout.replace(None); } else { self.timeout.borrow_mut().replace(Duration::from_secs(0)); } - if self.internal_setblocking(value) { - Ok(()) + if let Some(conn) = self.con.borrow_mut().as_mut() { + return match conn.setblocking(value) { + Ok(_) => Ok(()), + Err(err) => Err(vm.new_os_error(err.to_string())), + }; } else { - Err(vm.new_os_error("Set socket blocking error".to_string())) + Ok(()) } } - Err(_) => Err(vm.new_type_error(format!( - "an integer os required (got type {})", - &block.class().name.clone() - ))), + OptionalArg::Missing => { + self.timeout.replace(None); + Ok(()) + } } } - fn internal_setblocking(&self, block: bool) -> bool { - match self.con.borrow_mut().as_mut() { - Some(conn) => match conn { - Connection::TcpStream(con) => con.set_nonblocking(!block).is_ok(), - Connection::TcpListener(con) => con.set_nonblocking(!block).is_ok(), - Connection::UdpSocket(con) => con.set_nonblocking(!block).is_ok(), - }, - None => true, - } - } - - fn getblocking(self, vm: &VirtualMachine) -> PyResult { - Ok(vm.ctx.new_bool(self.internal_getblocking())) - } - - fn internal_getblocking(&self) -> bool { + fn getblocking(self, _vm: &VirtualMachine) -> PyResult> { match self.timeout.borrow().as_ref() { Some(duration) => { if duration.as_secs() != 0 { - true + Ok(Some(true)) } else { - false + Ok(Some(false)) } } - None => true, + None => Ok(Some(true)), } } - fn settimeout(self, timeout: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { - if vm.is_none(&timeout) { - return self.setblocking(vm.new_bool(true), vm); - } - match try_float(&timeout, vm) { - Ok(option_timeout) => { - let timeout = option_timeout.unwrap_or(0.0); + fn settimeout(self, option_timeout: OptionalArg, vm: &VirtualMachine) -> PyResult<()> { + match option_timeout { + OptionalArg::Present(timeout) => { self.timeout .borrow_mut() .replace(Duration::from_secs(timeout as u64)); - let block = timeout <= 0.0; + let block = timeout > 0.0; - self.internal_setblocking(block); - Ok(()) + if let Some(conn) = self.con.borrow_mut().as_mut() { + conn.setblocking(block).and_then(|_| { + conn.settimeout(Duration::from_secs(timeout as u64)) + }).map_err(|err| vm.new_os_error(err.to_string())).map(|_| ()) + } else { + Ok(()) + } } - Err(_) => Err(vm.new_type_error(format!( - "an integer required (got {} object)", - &timeout.class().name.clone() - ))), + OptionalArg::Missing => Ok(()), } } } @@ -521,6 +556,8 @@ fn socket_htonl(host: PyIntRef, vm: &VirtualMachine) -> PyResult { pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let ctx = &vm.ctx; + let socket_timeout = ctx.new_class("socket.timeout", vm.ctx.exceptions.os_error.clone()); + let socket_gaierror = ctx.new_class("socket.gaierror", vm.ctx.exceptions.os_error.clone()); let socket = py_class!(ctx, "socket", ctx.object(), { "__new__" => ctx.new_rustfunc(SocketRef::new), @@ -537,13 +574,15 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { "sendto" => ctx.new_rustfunc(SocketRef::sendto), "recvfrom" => ctx.new_rustfunc(SocketRef::recvfrom), "fileno" => ctx.new_rustfunc(SocketRef::fileno), - "gettimeout" => ctx.new_rustfunc(SocketRef::gettimeout), - "settimeout" => ctx.new_rustfunc(SocketRef::settimeout), "getblocking" => ctx.new_rustfunc(SocketRef::getblocking), "setblocking" => ctx.new_rustfunc(SocketRef::setblocking), + "gettimeout" => ctx.new_rustfunc(SocketRef::gettimeout), + "settimeout" => ctx.new_rustfunc(SocketRef::settimeout), }); let module = py_module!(vm, "socket", { + "error" => ctx.exceptions.os_error.clone(), + "timeout" => socket_timeout, "AF_INET" => ctx.new_int(AddressFamily::Inet as i32), "SOCK_STREAM" => ctx.new_int(SocketKind::Stream as i32), "SOCK_DGRAM" => ctx.new_int(SocketKind::Dgram as i32), From d58abd3a66e4b73d6d5ae33306e7288614e11fff Mon Sep 17 00:00:00 2001 From: lynskylate Date: Sun, 25 Aug 2019 22:31:21 +0800 Subject: [PATCH 3/6] Add timeout test --- tests/snippets/stdlib_socket.py | 29 +++++++++-------------------- vm/src/obj/objfloat.rs | 9 --------- vm/src/stdlib/socket.rs | 17 ++++++++++------- 3 files changed, 19 insertions(+), 36 deletions(-) diff --git a/tests/snippets/stdlib_socket.py b/tests/snippets/stdlib_socket.py index 2370fc9ed..ddd8d6ccc 100644 --- a/tests/snippets/stdlib_socket.py +++ b/tests/snippets/stdlib_socket.py @@ -138,23 +138,12 @@ with assertRaises(OSError): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: pass -connector = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -connection.settimeout(None) -assert connection.getblocking() == True -assert connection.gettimeout() == None - -connection.settimeout(0) -assert connection.getblocking() == False -assert connection.gettimeout() == 0 - -connection.setblocking(True) -assert connection.getblocking() == True -assert connection.gettimeout() == None - -connection.setblocking(False) -assert connection.getblocking() == False -assert connection.gettimeout() == 0.0 - -connection.settimeout(3) -assert connection.gettimeout() == 3 -assert connection.getblocking() == True \ No newline at end of file +with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as listener: + listener.bind(("127.0.0.1", 0)) + listener.listen(1) + connector = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + connector.connect(("127.0.0.1", listener.getsockname()[1])) + (connection, addr) = listener.accept() + connection.settimeout(1.0) + with assertRaises(OSError): + connection.recv(len(MESSAGE_A)) diff --git a/vm/src/obj/objfloat.rs b/vm/src/obj/objfloat.rs index 0a5d5b6f1..15f5ccf23 100644 --- a/vm/src/obj/objfloat.rs +++ b/vm/src/obj/objfloat.rs @@ -46,15 +46,6 @@ impl IntoPyObject for f32 { } } -impl TryFromObject for f64 { - fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { - try_float(&obj, vm)?.map_or_else( - || Err(vm.new_type_error(format!("Expect float object, but get {}", obj.class().name))), - |val| Ok(val), - ) - } -} - impl From for PyFloat { fn from(value: f64) -> Self { PyFloat { value } diff --git a/vm/src/stdlib/socket.rs b/vm/src/stdlib/socket.rs index a3dc9490a..868b9bf6a 100644 --- a/vm/src/stdlib/socket.rs +++ b/vm/src/stdlib/socket.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; use std::io; use std::io::Read; use std::io::Write; -use std::net::{Ipv4Addr, SocketAddr, TcpListener, TcpStream, ToSocketAddrs, UdpSocket }; +use std::net::{Ipv4Addr, SocketAddr, TcpListener, TcpStream, ToSocketAddrs, UdpSocket}; use std::time::Duration; #[cfg(all(unix, not(target_os = "redox")))] @@ -25,7 +25,6 @@ use crate::obj::objtype::PyClassRef; use crate::stdlib::os::convert_nix_error; use num_bigint::Sign; use num_traits::ToPrimitive; -use itertools::Itertools; #[derive(Debug, Copy, Clone)] enum AddressFamily { @@ -225,8 +224,11 @@ impl SocketRef { Ok(mut sock_addrs) => { if sock_addrs.len() == 0 { let error_type = vm.class("socket", "gaierror"); - return Err(vm.new_exception(error_type, "nodename nor servname provided, or not known".to_string())) - }else{ + return Err(vm.new_exception( + error_type, + "nodename nor servname provided, or not known".to_string(), + )); + } else { sock_addrs.next().unwrap() } } @@ -466,9 +468,10 @@ impl SocketRef { let block = timeout > 0.0; if let Some(conn) = self.con.borrow_mut().as_mut() { - conn.setblocking(block).and_then(|_| { - conn.settimeout(Duration::from_secs(timeout as u64)) - }).map_err(|err| vm.new_os_error(err.to_string())).map(|_| ()) + conn.setblocking(block) + .and_then(|_| conn.settimeout(Duration::from_secs(timeout as u64))) + .map_err(|err| vm.new_os_error(err.to_string())) + .map(|_| ()) } else { Ok(()) } From bd72869c345f3d4fa2f887990ae85e7adda29641 Mon Sep 17 00:00:00 2001 From: lynskylate Date: Mon, 26 Aug 2019 01:04:04 +0800 Subject: [PATCH 4/6] Repalce OptionalArg to Option --- vm/src/stdlib/socket.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/vm/src/stdlib/socket.rs b/vm/src/stdlib/socket.rs index 868b9bf6a..5ba62110c 100644 --- a/vm/src/stdlib/socket.rs +++ b/vm/src/stdlib/socket.rs @@ -12,12 +12,12 @@ use gethostname::gethostname; use byteorder::{BigEndian, ByteOrder}; -use crate::function::{OptionalArg, PyFuncArgs}; +use crate::function::PyFuncArgs; use crate::obj::objbytes::PyBytesRef; use crate::obj::objint::PyIntRef; use crate::obj::objstr::PyStringRef; use crate::obj::objtuple::PyTupleRef; -use crate::pyobject::{PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol}; +use crate::pyobject::{PyObjectRef, PyRef, PyResult, PyValue, TryFromObject}; use crate::vm::VirtualMachine; use crate::obj::objtype::PyClassRef; @@ -421,9 +421,9 @@ impl SocketRef { } } - fn setblocking(self, block: OptionalArg, vm: &VirtualMachine) -> PyResult<()> { + fn setblocking(self, block: Option, vm: &VirtualMachine) -> PyResult<()> { match block { - OptionalArg::Present(value) => { + Some(value) => { if value { self.timeout.replace(None); } else { @@ -438,9 +438,9 @@ impl SocketRef { Ok(()) } } - OptionalArg::Missing => { - self.timeout.replace(None); - Ok(()) + None => { + // Avoid converting None to bool + Err(vm.new_type_error("an bool is required".to_string())) } } } @@ -458,9 +458,9 @@ impl SocketRef { } } - fn settimeout(self, option_timeout: OptionalArg, vm: &VirtualMachine) -> PyResult<()> { + fn settimeout(self, option_timeout: Option, vm: &VirtualMachine) -> PyResult<()> { match option_timeout { - OptionalArg::Present(timeout) => { + Some(timeout) => { self.timeout .borrow_mut() .replace(Duration::from_secs(timeout as u64)); @@ -476,7 +476,10 @@ impl SocketRef { Ok(()) } } - OptionalArg::Missing => Ok(()), + None => { + self.timeout.replace(None); + Ok(()) + } } } } @@ -586,6 +589,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let module = py_module!(vm, "socket", { "error" => ctx.exceptions.os_error.clone(), "timeout" => socket_timeout, + "gaierror" => socket_gaierror, "AF_INET" => ctx.new_int(AddressFamily::Inet as i32), "SOCK_STREAM" => ctx.new_int(SocketKind::Stream as i32), "SOCK_DGRAM" => ctx.new_int(SocketKind::Dgram as i32), From 1e1248090ee6590fdf9f131f34b8f37310d25017 Mon Sep 17 00:00:00 2001 From: lynskylate Date: Mon, 26 Aug 2019 01:08:12 +0800 Subject: [PATCH 5/6] Fix clippy error --- vm/src/stdlib/socket.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/src/stdlib/socket.rs b/vm/src/stdlib/socket.rs index 5ba62110c..4f4384741 100644 --- a/vm/src/stdlib/socket.rs +++ b/vm/src/stdlib/socket.rs @@ -237,7 +237,7 @@ impl SocketRef { return Err(vm.new_exception(error_type, e.to_string())); } }; - TcpStream::connect_timeout(&sock_addr, duration.clone()) + TcpStream::connect_timeout(&sock_addr, *duration) } else { TcpStream::connect(address_string) }; From 936af5b9f89537be02263586447aa2ca7a0bdf84 Mon Sep 17 00:00:00 2001 From: lynskylate Date: Mon, 26 Aug 2019 01:44:56 +0800 Subject: [PATCH 6/6] Rename args --- vm/src/stdlib/socket.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vm/src/stdlib/socket.rs b/vm/src/stdlib/socket.rs index 4f4384741..e0fd0a505 100644 --- a/vm/src/stdlib/socket.rs +++ b/vm/src/stdlib/socket.rs @@ -458,8 +458,8 @@ impl SocketRef { } } - fn settimeout(self, option_timeout: Option, vm: &VirtualMachine) -> PyResult<()> { - match option_timeout { + fn settimeout(self, timeout: Option, vm: &VirtualMachine) -> PyResult<()> { + match timeout { Some(timeout) => { self.timeout .borrow_mut()