Merge pull request #1599 from RustPython/coolreader18/asyncio-pre

Prerequisites for asyncio
This commit is contained in:
Noah
2019-11-19 10:50:22 -06:00
committed by GitHub
23 changed files with 487 additions and 410 deletions

1
Cargo.lock generated
View File

@@ -1295,6 +1295,7 @@ dependencies = [
"flamer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"flate2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)",
"gethostname 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hexf-parse 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@@ -193,6 +193,7 @@ class _localimpl:
@contextmanager
def _patch(self):
old = object.__getattribute__(self, '__dict__')
impl = object.__getattribute__(self, '_local__impl')
try:
dct = impl.get_dict()
@@ -203,6 +204,7 @@ def _patch(self):
with impl.locallock:
object.__setattr__(self, '__dict__', dct)
yield
object.__setattr__(self, '__dict__', old)
class local:

9
Lib/atexit.py vendored Normal file
View File

@@ -0,0 +1,9 @@
# Dummy implementation of atexit
def register(func, *args, **kwargs):
return func
def unregister(func):
pass

View File

@@ -65,6 +65,13 @@ impl Default for CodeFlags {
}
}
impl CodeFlags {
pub const NAME_MAPPING: &'static [(&'static str, CodeFlags)] = &[
("GENERATOR", CodeFlags::IS_GENERATOR),
("COROUTINE", CodeFlags::IS_COROUTINE),
];
}
#[derive(Serialize, Debug, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Label(usize);

View File

@@ -17,3 +17,8 @@ assert MyObject().__lt__(MyObject()) == NotImplemented
assert MyObject().__le__(MyObject()) == NotImplemented
assert MyObject().__gt__(MyObject()) == NotImplemented
assert MyObject().__ge__(MyObject()) == NotImplemented
obj = MyObject()
assert not hasattr(obj, 'a')
obj.__dict__ = {'a': 1}
assert obj.a == 1

View File

@@ -32,6 +32,7 @@ num-rational = "0.2.2"
num-iter = "0.1.39"
rand = "0.7"
rand_distr = "0.2"
getrandom = "0.1"
log = "0.4"
rustpython-derive = {path = "../derive", version = "0.1.1"}
rustpython-parser = {path = "../parser", optional = true, version = "0.1.1"}
@@ -88,7 +89,7 @@ socket2 = { version = "0.3", features = ["unix"] }
[target."cfg(windows)".dependencies.winapi]
version = "0.3"
features = ["winsock2", "handleapi", "ws2def", "std"]
features = ["winsock2", "handleapi", "ws2def", "std", "winbase"]
[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen = "0.2"

View File

@@ -252,9 +252,15 @@ fn make_scope(vm: &VirtualMachine, scope: ScopeArgs) -> PyResult<Scope> {
let globals = match globals {
Some(dict) => {
if !dict.contains_key("__builtins__", vm) {
let builtins_dict = vm.builtins.dict.as_ref().unwrap().as_object();
dict.set_item("__builtins__", builtins_dict.clone(), vm)
.unwrap();
let builtins_dict = vm
.builtins
.dict
.as_ref()
.unwrap()
.borrow()
.as_object()
.clone();
dict.set_item("__builtins__", builtins_dict, vm).unwrap();
}
dict
}
@@ -870,23 +876,31 @@ pub fn make_module(vm: &VirtualMachine, module: PyObjectRef) {
"IndexError" => ctx.exceptions.index_error.clone(),
"ImportError" => ctx.exceptions.import_error.clone(),
"LookupError" => ctx.exceptions.lookup_error.clone(),
"FileNotFoundError" => ctx.exceptions.file_not_found_error.clone(),
"FileExistsError" => ctx.exceptions.file_exists_error.clone(),
"StopIteration" => ctx.exceptions.stop_iteration.clone(),
"StopAsyncIteration" => ctx.exceptions.stop_async_iteration.clone(),
"SystemError" => ctx.exceptions.system_error.clone(),
"PermissionError" => ctx.exceptions.permission_error.clone(),
"UnicodeError" => ctx.exceptions.unicode_error.clone(),
"UnicodeDecodeError" => ctx.exceptions.unicode_decode_error.clone(),
"UnicodeEncodeError" => ctx.exceptions.unicode_encode_error.clone(),
"UnicodeTranslateError" => ctx.exceptions.unicode_translate_error.clone(),
"ZeroDivisionError" => ctx.exceptions.zero_division_error.clone(),
"KeyError" => ctx.exceptions.key_error.clone(),
"OSError" => ctx.exceptions.os_error.clone(),
"ModuleNotFoundError" => ctx.exceptions.module_not_found_error.clone(),
"EOFError" => ctx.exceptions.eof_error.clone(),
"MemoryError" => ctx.exceptions.memory_error.clone(),
"OSError" => ctx.exceptions.os_error.clone(),
"FileNotFoundError" => ctx.exceptions.file_not_found_error.clone(),
"PermissionError" => ctx.exceptions.permission_error.clone(),
"FileExistsError" => ctx.exceptions.file_exists_error.clone(),
"BlockingIOError" => ctx.exceptions.blocking_io_error.clone(),
"InterruptedError" => ctx.exceptions.interrupted_error.clone(),
"ConnectionError" => ctx.exceptions.connection_error.clone(),
"ConnectionResetError" => ctx.exceptions.connection_reset_error.clone(),
"ConnectionRefusedError" => ctx.exceptions.connection_refused_error.clone(),
"ConnectionAbortedError" => ctx.exceptions.connection_aborted_error.clone(),
"BrokenPipeError" => ctx.exceptions.broken_pipe_error.clone(),
// Warnings
"Warning" => ctx.exceptions.warning.clone(),
"BytesWarning" => ctx.exceptions.bytes_warning.clone(),

View File

@@ -228,8 +228,6 @@ pub struct ExceptionZoo {
pub attribute_error: PyClassRef,
pub base_exception_type: PyClassRef,
pub exception_type: PyClassRef,
pub file_not_found_error: PyClassRef,
pub file_exists_error: PyClassRef,
pub import_error: PyClassRef,
pub index_error: PyClassRef,
pub key_error: PyClassRef,
@@ -238,9 +236,7 @@ pub struct ExceptionZoo {
pub name_error: PyClassRef,
pub not_implemented_error: PyClassRef,
pub recursion_error: PyClassRef,
pub os_error: PyClassRef,
pub overflow_error: PyClassRef,
pub permission_error: PyClassRef,
pub reference_error: PyClassRef,
pub runtime_error: PyClassRef,
pub stop_iteration: PyClassRef,
@@ -259,6 +255,18 @@ pub struct ExceptionZoo {
pub eof_error: PyClassRef,
pub memory_error: PyClassRef,
pub os_error: PyClassRef,
pub file_not_found_error: PyClassRef,
pub permission_error: PyClassRef,
pub file_exists_error: PyClassRef,
pub blocking_io_error: PyClassRef,
pub interrupted_error: PyClassRef,
pub connection_error: PyClassRef,
pub connection_reset_error: PyClassRef,
pub connection_refused_error: PyClassRef,
pub connection_aborted_error: PyClassRef,
pub broken_pipe_error: PyClassRef,
pub warning: PyClassRef,
pub bytes_warning: PyClassRef,
pub unicode_warning: PyClassRef,
@@ -289,7 +297,6 @@ impl ExceptionZoo {
let key_error = create_type("KeyError", &type_type, &exception_type);
let lookup_error = create_type("LookupError", &type_type, &exception_type);
let name_error = create_type("NameError", &type_type, &exception_type);
let os_error = create_type("OSError", &type_type, &exception_type);
let runtime_error = create_type("RuntimeError", &type_type, &exception_type);
let reference_error = create_type("ReferenceError", &type_type, &exception_type);
let stop_iteration = create_type("StopIteration", &type_type, &exception_type);
@@ -303,9 +310,6 @@ impl ExceptionZoo {
let module_not_found_error = create_type("ModuleNotFoundError", &type_type, &import_error);
let not_implemented_error = create_type("NotImplementedError", &type_type, &runtime_error);
let recursion_error = create_type("RecursionError", &type_type, &runtime_error);
let file_not_found_error = create_type("FileNotFoundError", &type_type, &os_error);
let permission_error = create_type("PermissionError", &type_type, &os_error);
let file_exists_error = create_type("FileExistsError", &type_type, &os_error);
let eof_error = create_type("EOFError", &type_type, &exception_type);
let indentation_error = create_type("IndentationError", &type_type, &syntax_error);
let tab_error = create_type("TabError", &type_type, &indentation_error);
@@ -316,6 +320,23 @@ impl ExceptionZoo {
create_type("UnicodeTranslateError", &type_type, &unicode_error);
let memory_error = create_type("MemoryError", &type_type, &exception_type);
// os errors
let os_error = create_type("OSError", &type_type, &exception_type);
let file_not_found_error = create_type("FileNotFoundError", &type_type, &os_error);
let permission_error = create_type("PermissionError", &type_type, &os_error);
let file_exists_error = create_type("FileExistsError", &type_type, &os_error);
let blocking_io_error = create_type("BlockingIOError", &type_type, &os_error);
let interrupted_error = create_type("InterruptedError", &type_type, &os_error);
let connection_error = create_type("ConnectionError", &type_type, &os_error);
let connection_reset_error =
create_type("ConnectionResetError", &type_type, &connection_error);
let connection_refused_error =
create_type("ConnectionRefusedError", &type_type, &connection_error);
let connection_aborted_error =
create_type("ConnectionAbortedError", &type_type, &connection_error);
let broken_pipe_error = create_type("BrokenPipeError", &type_type, &connection_error);
let warning = create_type("Warning", &type_type, &exception_type);
let bytes_warning = create_type("BytesWarning", &type_type, &warning);
let unicode_warning = create_type("UnicodeWarning", &type_type, &warning);
@@ -339,8 +360,6 @@ impl ExceptionZoo {
attribute_error,
base_exception_type,
exception_type,
file_not_found_error,
file_exists_error,
import_error,
index_error,
key_error,
@@ -349,9 +368,7 @@ impl ExceptionZoo {
name_error,
not_implemented_error,
recursion_error,
os_error,
overflow_error,
permission_error,
runtime_error,
stop_iteration,
stop_async_iteration,
@@ -368,6 +385,17 @@ impl ExceptionZoo {
zero_division_error,
eof_error,
memory_error,
os_error,
file_not_found_error,
permission_error,
file_exists_error,
blocking_io_error,
interrupted_error,
connection_error,
connection_reset_error,
connection_refused_error,
connection_aborted_error,
broken_pipe_error,
warning,
bytes_warning,
unicode_warning,

View File

@@ -699,7 +699,7 @@ impl Frame {
// Grab all the names from the module and put them in the context
if let Some(dict) = &module.dict {
for (k, v) in dict {
for (k, v) in &*dict.borrow() {
let k = vm.to_str(&k)?;
let k = k.as_str();
if !k.starts_with('_') {

View File

@@ -116,22 +116,22 @@ macro_rules! no_kwargs {
#[macro_export]
macro_rules! py_module {
( $vm:expr, $module_name:expr, { $($name:expr => $value:expr),* $(,)* }) => {{
( $vm:expr, $module_name:expr, { $($name:expr => $value:expr),* $(,)? }) => {{
let module = $vm.new_module($module_name, $vm.ctx.new_dict());
$(
$vm.set_attr(&module, $name, $value).unwrap();
)*
$crate::extend_module!($vm, module, { $($name => $value),* });
module
}};
}
#[macro_export]
macro_rules! extend_module {
( $vm:expr, $module:expr, { $($name:expr => $value:expr),* $(,)* }) => {
( $vm:expr, $module:expr, { $($name:expr => $value:expr),* $(,)? }) => {{
#[allow(unused_variables)]
let module: &$crate::pyobject::PyObjectRef = &$module;
$(
$vm.set_attr(&$module, $name, $value).unwrap();
$vm.__module_set_attr(&module, $name, $value).unwrap();
)*
}
}};
}
#[macro_export]

View File

@@ -86,6 +86,10 @@ impl PyCodeRef {
fn co_name(self, _vm: &VirtualMachine) -> String {
self.code.obj_name.clone()
}
fn co_flags(self, _vm: &VirtualMachine) -> u8 {
self.code.flags.bits()
}
}
pub fn init(context: &PyContext) {
@@ -99,5 +103,6 @@ pub fn init(context: &PyContext) {
"co_firstlineno" => context.new_property(PyCodeRef::co_firstlineno),
"co_kwonlyargcount" => context.new_property(PyCodeRef::co_kwonlyargcount),
"co_name" => context.new_property(PyCodeRef::co_name),
"co_flags" => context.new_property(PyCodeRef::co_flags),
});
}

View File

@@ -64,11 +64,24 @@ pub struct PyMethod {
// TODO: these shouldn't be public
pub object: PyObjectRef,
pub function: PyObjectRef,
pub actually_bind: bool,
}
impl PyMethod {
pub fn new(object: PyObjectRef, function: PyObjectRef) -> Self {
PyMethod { object, function }
PyMethod {
object,
function,
actually_bind: true,
}
}
pub fn new_nobind(object: PyObjectRef, function: PyObjectRef) -> Self {
PyMethod {
object,
function,
actually_bind: false,
}
}
fn getattribute(&self, name: PyStringRef, vm: &VirtualMachine) -> PyResult {

View File

@@ -50,7 +50,7 @@ impl PyModuleRef {
let zelf = PyModule {}.into_ref_with_type(vm, cls)?;
init_module_dict(
vm,
zelf.as_object().dict.as_ref().unwrap(),
&zelf.as_object().dict.as_ref().unwrap().borrow(),
name.into_object(),
doc.flat_option()
.map_or_else(|| vm.get_none(), PyRef::into_object),

View File

@@ -77,7 +77,7 @@ fn object_setattr(
}
if let Some(ref dict) = obj.clone().dict {
dict.set_item(attr_name.as_str(), value, vm)?;
dict.borrow().set_item(attr_name.as_str(), value, vm)?;
Ok(())
} else {
Err(vm.new_attribute_error(format!(
@@ -98,7 +98,7 @@ fn object_delattr(obj: PyObjectRef, attr_name: PyStringRef, vm: &VirtualMachine)
}
if let Some(ref dict) = obj.dict {
dict.del_item(attr_name.as_str(), vm)?;
dict.borrow().del_item(attr_name.as_str(), vm)?;
Ok(())
} else {
Err(vm.new_attribute_error(format!(
@@ -130,7 +130,7 @@ pub fn object_dir(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyList> {
if let Some(object_dict) = &obj.dict {
vm.invoke(
&vm.get_attribute(dict.clone().into_object(), "update")?,
object_dict.clone().into_object(),
object_dict.borrow().clone().into_object(),
)?;
}
@@ -210,20 +210,22 @@ fn object_class_setter(
fn object_dict(object: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyDictRef> {
if let Some(ref dict) = object.dict {
Ok(dict.clone())
Ok(dict.borrow().clone())
} else {
Err(vm.new_attribute_error("no dictionary.".to_string()))
}
}
fn object_dict_setter(
_instance: PyObjectRef,
_value: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult {
Err(vm.new_not_implemented_error(
"Setting __dict__ attribute on an object isn't yet implemented".to_string(),
))
fn object_dict_setter(instance: PyObjectRef, value: PyDictRef, vm: &VirtualMachine) -> PyResult {
if let Some(dict) = &instance.dict {
*dict.borrow_mut() = value;
Ok(vm.get_none())
} else {
Err(vm.new_attribute_error(format!(
"'{}' object has no attribute '__dict__'",
instance.class().name
)))
}
}
fn object_getattribute(obj: PyObjectRef, name: PyStringRef, vm: &VirtualMachine) -> PyResult {

View File

@@ -1,5 +1,5 @@
use std::any::Any;
use std::cell::Cell;
use std::cell::{Cell, RefCell};
use std::collections::HashMap;
use std::fmt;
use std::marker::PhantomData;
@@ -522,7 +522,7 @@ impl PyContext {
pub fn new_instance(&self, class: PyClassRef, dict: Option<PyDictRef>) -> PyObjectRef {
PyObject {
typ: class,
dict,
dict: dict.map(RefCell::new),
payload: objobject::PyInstance,
}
.into_ref()
@@ -566,7 +566,7 @@ where
T: ?Sized + PyObjectPayload,
{
pub typ: PyClassRef,
pub dict: Option<PyDictRef>, // __dict__ member
pub dict: Option<RefCell<PyDictRef>>, // __dict__ member
pub payload: T,
}
@@ -1038,7 +1038,12 @@ where
{
#[allow(clippy::new_ret_no_self)]
pub fn new(payload: T, typ: PyClassRef, dict: Option<PyDictRef>) -> PyObjectRef {
PyObject { typ, dict, payload }.into_ref()
PyObject {
typ,
dict: dict.map(RefCell::new),
payload,
}
.into_ref()
}
// Move this object into a reference object, transferring ownership.

View File

@@ -1,5 +1,6 @@
use crate::bytecode::CodeFlags;
use crate::obj::objcode::PyCodeRef;
use crate::pyobject::{PyObjectRef, PyResult, TryFromObject};
use crate::pyobject::{ItemProtocol, PyObjectRef, PyResult, TryFromObject};
use crate::vm::VirtualMachine;
fn dis_dis(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
@@ -17,11 +18,25 @@ fn dis_disassemble(co: PyObjectRef, vm: &VirtualMachine) -> PyResult {
Ok(vm.get_none())
}
fn dis_compiler_flag_names(vm: &VirtualMachine) -> PyObjectRef {
let dict = vm.ctx.new_dict();
for (name, flag) in CodeFlags::NAME_MAPPING {
dict.set_item(
&vm.ctx.new_int(flag.bits()),
vm.ctx.new_str(name.to_string()),
vm,
)
.unwrap();
}
dict.into_object()
}
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
let ctx = &vm.ctx;
py_module!(vm, "dis", {
"dis" => ctx.new_rustfunc(dis_dis),
"disassemble" => ctx.new_rustfunc(dis_disassemble)
"disassemble" => ctx.new_rustfunc(dis_disassemble),
"COMPILER_FLAG_NAMES" => dis_compiler_flag_names(vm),
})
}

View File

@@ -15,334 +15,206 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
module
}
#[cfg(target_os = "linux")]
const ERROR_CODES: &[(&str, i32)] = &[
("ENODEV", libc::ENODEV),
("ENOCSI", libc::ENOCSI),
("EHOSTUNREACH", libc::EHOSTUNREACH),
("ENOMSG", libc::ENOMSG),
("EUCLEAN", libc::EUCLEAN),
("EL2NSYNC", libc::EL2NSYNC),
("EL2HLT", libc::EL2HLT),
("ENODATA", libc::ENODATA),
("ENOTBLK", libc::ENOTBLK),
("ENOSYS", libc::ENOSYS),
("EPIPE", libc::EPIPE),
("EINVAL", libc::EINVAL),
("EOVERFLOW", libc::EOVERFLOW),
("EADV", libc::EADV),
("EINTR", libc::EINTR),
("EUSERS", libc::EUSERS),
("ENOTEMPTY", libc::ENOTEMPTY),
("ENOBUFS", libc::ENOBUFS),
("EPROTO", libc::EPROTO),
("EREMOTE", libc::EREMOTE),
("ENAVAIL", libc::ENAVAIL),
("ECHILD", libc::ECHILD),
("ELOOP", libc::ELOOP),
("EXDEV", libc::EXDEV),
("E2BIG", libc::E2BIG),
("ESRCH", libc::ESRCH),
("EMSGSIZE", libc::EMSGSIZE),
("EAFNOSUPPORT", libc::EAFNOSUPPORT),
("EBADR", libc::EBADR),
("EHOSTDOWN", libc::EHOSTDOWN),
("EPFNOSUPPORT", libc::EPFNOSUPPORT),
("ENOPROTOOPT", libc::ENOPROTOOPT),
("EBUSY", libc::EBUSY),
("EAGAIN", libc::EAGAIN),
("EBADFD", libc::EBADFD),
("EDOTDOT", libc::EDOTDOT),
("EISCONN", libc::EISCONN),
("ENOANO", libc::ENOANO),
("ESHUTDOWN", libc::ESHUTDOWN),
("ECHRNG", libc::ECHRNG),
("ELIBBAD", libc::ELIBBAD),
("ENONET", libc::ENONET),
("EBADE", libc::EBADE),
("EBADF", libc::EBADF),
("EMULTIHOP", libc::EMULTIHOP),
("EIO", libc::EIO),
("EUNATCH", libc::EUNATCH),
("EPROTOTYPE", libc::EPROTOTYPE),
("ENOSPC", libc::ENOSPC),
("ENOEXEC", libc::ENOEXEC),
("EALREADY", libc::EALREADY),
("ENETDOWN", libc::ENETDOWN),
("ENOTNAM", libc::ENOTNAM),
("EACCES", libc::EACCES),
("ELNRNG", libc::ELNRNG),
("EILSEQ", libc::EILSEQ),
("ENOTDIR", libc::ENOTDIR),
("ENOTUNIQ", libc::ENOTUNIQ),
("EPERM", libc::EPERM),
("EDOM", libc::EDOM),
("EXFULL", libc::EXFULL),
("ECONNREFUSED", libc::ECONNREFUSED),
("EISDIR", libc::EISDIR),
("EPROTONOSUPPORT", libc::EPROTONOSUPPORT),
("EROFS", libc::EROFS),
("EADDRNOTAVAIL", libc::EADDRNOTAVAIL),
("EIDRM", libc::EIDRM),
("ECOMM", libc::ECOMM),
("ESRMNT", libc::ESRMNT),
("EREMOTEIO", libc::EREMOTEIO),
("EL3RST", libc::EL3RST),
("EBADMSG", libc::EBADMSG),
("ENFILE", libc::ENFILE),
("ELIBMAX", libc::ELIBMAX),
("ESPIPE", libc::ESPIPE),
("ENOLINK", libc::ENOLINK),
("ENETRESET", libc::ENETRESET),
("ETIMEDOUT", libc::ETIMEDOUT),
("ENOENT", libc::ENOENT),
("EEXIST", libc::EEXIST),
("EDQUOT", libc::EDQUOT),
("ENOSTR", libc::ENOSTR),
("EBADSLT", libc::EBADSLT),
("EBADRQC", libc::EBADRQC),
("ELIBACC", libc::ELIBACC),
("EFAULT", libc::EFAULT),
("EFBIG", libc::EFBIG),
("EDEADLOCK", libc::EDEADLOCK),
("ENOTCONN", libc::ENOTCONN),
("EDESTADDRREQ", libc::EDESTADDRREQ),
("ELIBSCN", libc::ELIBSCN),
("ENOLCK", libc::ENOLCK),
("EISNAM", libc::EISNAM),
("ECONNABORTED", libc::ECONNABORTED),
("ENETUNREACH", libc::ENETUNREACH),
("ESTALE", libc::ESTALE),
("ENOSR", libc::ENOSR),
("ENOMEM", libc::ENOMEM),
("ENOTSOCK", libc::ENOTSOCK),
("ESTRPIPE", libc::ESTRPIPE),
("EMLINK", libc::EMLINK),
("ERANGE", libc::ERANGE),
("ELIBEXEC", libc::ELIBEXEC),
("EL3HLT", libc::EL3HLT),
("ECONNRESET", libc::ECONNRESET),
("EADDRINUSE", libc::EADDRINUSE),
("ENOTSUP", libc::ENOTSUP),
("EREMCHG", libc::EREMCHG),
("ENAMETOOLONG", libc::ENAMETOOLONG),
("ENOTTY", libc::ENOTTY),
("ERESTART", libc::ERESTART),
("ESOCKTNOSUPPORT", libc::ESOCKTNOSUPPORT),
("ETIME", libc::ETIME),
("EBFONT", libc::EBFONT),
("ETOOMANYREFS", libc::ETOOMANYREFS),
("EMFILE", libc::EMFILE),
("ETXTBSY", libc::ETXTBSY),
("EINPROGRESS", libc::EINPROGRESS),
("ENXIO", libc::ENXIO),
("ENOPKG", libc::ENOPKG),
("ENOMEDIUM", libc::ENOMEDIUM),
("EMEDIUMTYPE", libc::EMEDIUMTYPE),
("ECANCELED", libc::ECANCELED),
("ENOKEY", libc::ENOKEY),
("EKEYEXPIRED", libc::EKEYEXPIRED),
("EKEYREVOKED", libc::EKEYREVOKED),
("EKEYREJECTED", libc::EKEYREJECTED),
("EOWNERDEAD", libc::EOWNERDEAD),
("ENOTRECOVERABLE", libc::ENOTRECOVERABLE),
("ERFKILL", libc::ERFKILL),
];
#[rustfmt::skip]
#[allow(unused)]
pub mod errors {
pub use libc::*;
#[cfg(windows)]
pub use winapi::shared::winerror::*;
#[cfg(windows)] pub const EACCES: i32 = WSAEACCES as _;
#[cfg(windows)] pub const EADDRINUSE: i32 = WSAEADDRINUSE as _;
#[cfg(windows)] pub const EADDRNOTAVAIL: i32 = WSAEADDRNOTAVAIL as _;
#[cfg(windows)] pub const EAFNOSUPPORT: i32 = WSAEAFNOSUPPORT as _;
#[cfg(windows)] pub const EALREADY: i32 = WSAEALREADY as _;
#[cfg(windows)] pub const EBADF: i32 = WSAEBADF as _;
#[cfg(windows)] pub const ECANCELED: i32 = WSAECANCELLED as _;
#[cfg(windows)] pub const ECONNABORTED: i32 = WSAECONNABORTED as _;
#[cfg(windows)] pub const ECONNREFUSED: i32 = WSAECONNREFUSED as _;
#[cfg(windows)] pub const ECONNRESET: i32 = WSAECONNRESET as _;
#[cfg(windows)] pub const EDESTADDRREQ: i32 = WSAEDESTADDRREQ as _;
#[cfg(windows)] pub const EDISCON: i32 = WSAEDISCON as _;
#[cfg(windows)] pub const EDQUOT: i32 = WSAEDQUOT as _;
#[cfg(windows)] pub const EFAULT: i32 = WSAEFAULT as _;
#[cfg(windows)] pub const EHOSTDOWN: i32 = WSAEHOSTDOWN as _;
#[cfg(windows)] pub const EHOSTUNREACH: i32 = WSAEHOSTUNREACH as _;
#[cfg(windows)] pub const EINPROGRESS: i32 = WSAEINPROGRESS as _;
#[cfg(windows)] pub const EINTR: i32 = WSAEINTR as _;
#[cfg(windows)] pub const EINVAL: i32 = WSAEINVAL as _;
#[cfg(windows)] pub const EINVALIDPROCTABLE: i32 = WSAEINVALIDPROCTABLE as _;
#[cfg(windows)] pub const EINVALIDPROVIDER: i32 = WSAEINVALIDPROVIDER as _;
#[cfg(windows)] pub const EISCONN: i32 = WSAEISCONN as _;
#[cfg(windows)] pub const ELOOP: i32 = WSAELOOP as _;
#[cfg(windows)] pub const EMFILE: i32 = WSAEMFILE as _;
#[cfg(windows)] pub const EMSGSIZE: i32 = WSAEMSGSIZE as _;
#[cfg(windows)] pub const ENAMETOOLONG: i32 = WSAENAMETOOLONG as _;
#[cfg(windows)] pub const ENETDOWN: i32 = WSAENETDOWN as _;
#[cfg(windows)] pub const ENETRESET: i32 = WSAENETRESET as _;
#[cfg(windows)] pub const ENETUNREACH: i32 = WSAENETUNREACH as _;
#[cfg(windows)] pub const ENOBUFS: i32 = WSAENOBUFS as _;
#[cfg(windows)] pub const ENOMORE: i32 = WSAENOMORE as _;
#[cfg(windows)] pub const ENOPROTOOPT: i32 = WSAENOPROTOOPT as _;
#[cfg(windows)] pub const ENOTCONN: i32 = WSAENOTCONN as _;
#[cfg(windows)] pub const ENOTEMPTY: i32 = WSAENOTEMPTY as _;
#[cfg(windows)] pub const ENOTSOCK: i32 = WSAENOTSOCK as _;
#[cfg(windows)] pub const EOPNOTSUPP: i32 = WSAEOPNOTSUPP as _;
#[cfg(windows)] pub const EPFNOSUPPORT: i32 = WSAEPFNOSUPPORT as _;
#[cfg(windows)] pub const EPROCLIM: i32 = WSAEPROCLIM as _;
#[cfg(windows)] pub const EPROTONOSUPPORT: i32 = WSAEPROTONOSUPPORT as _;
#[cfg(windows)] pub const EPROTOTYPE: i32 = WSAEPROTOTYPE as _;
#[cfg(windows)] pub const EPROVIDERFAILEDINIT: i32 = WSAEPROVIDERFAILEDINIT as _;
#[cfg(windows)] pub const EREFUSED: i32 = WSAEREFUSED as _;
#[cfg(windows)] pub const EREMOTE: i32 = WSAEREMOTE as _;
#[cfg(windows)] pub const ESHUTDOWN: i32 = WSAESHUTDOWN as _;
#[cfg(windows)] pub const ESOCKTNOSUPPORT: i32 = WSAESOCKTNOSUPPORT as _;
#[cfg(windows)] pub const ESTALE: i32 = WSAESTALE as _;
#[cfg(windows)] pub const ETIMEDOUT: i32 = WSAETIMEDOUT as _;
#[cfg(windows)] pub const ETOOMANYREFS: i32 = WSAETOOMANYREFS as _;
#[cfg(windows)] pub const EUSERS: i32 = WSAEUSERS as _;
#[cfg(windows)] pub const EWOULDBLOCK: i32 = WSAEWOULDBLOCK as _;
}
#[cfg(all(unix, not(target_os = "linux")))]
const ERROR_CODES: &[(&str, i32)] = &[
("ENODEV", libc::ENODEV),
("EHOSTUNREACH", libc::EHOSTUNREACH),
("ENOMSG", libc::ENOMSG),
("ENODATA", libc::ENODATA),
("ENOTBLK", libc::ENOTBLK),
("ENOSYS", libc::ENOSYS),
("EPIPE", libc::EPIPE),
("EINVAL", libc::EINVAL),
("EOVERFLOW", libc::EOVERFLOW),
("EINTR", libc::EINTR),
("EUSERS", libc::EUSERS),
("ENOTEMPTY", libc::ENOTEMPTY),
("ENOBUFS", libc::ENOBUFS),
("EPROTO", libc::EPROTO),
("EREMOTE", libc::EREMOTE),
("ECHILD", libc::ECHILD),
("ELOOP", libc::ELOOP),
("EXDEV", libc::EXDEV),
("E2BIG", libc::E2BIG),
("ESRCH", libc::ESRCH),
("EMSGSIZE", libc::EMSGSIZE),
("EAFNOSUPPORT", libc::EAFNOSUPPORT),
("EHOSTDOWN", libc::EHOSTDOWN),
("EPFNOSUPPORT", libc::EPFNOSUPPORT),
("ENOPROTOOPT", libc::ENOPROTOOPT),
("EBUSY", libc::EBUSY),
("EAGAIN", libc::EAGAIN),
("EISCONN", libc::EISCONN),
("ESHUTDOWN", libc::ESHUTDOWN),
("EBADF", libc::EBADF),
("EMULTIHOP", libc::EMULTIHOP),
("EIO", libc::EIO),
("EPROTOTYPE", libc::EPROTOTYPE),
("ENOSPC", libc::ENOSPC),
("ENOEXEC", libc::ENOEXEC),
("EALREADY", libc::EALREADY),
("ENETDOWN", libc::ENETDOWN),
("EACCES", libc::EACCES),
("EILSEQ", libc::EILSEQ),
("ENOTDIR", libc::ENOTDIR),
("EPERM", libc::EPERM),
("EDOM", libc::EDOM),
("ECONNREFUSED", libc::ECONNREFUSED),
("EISDIR", libc::EISDIR),
("EPROTONOSUPPORT", libc::EPROTONOSUPPORT),
("EROFS", libc::EROFS),
("EADDRNOTAVAIL", libc::EADDRNOTAVAIL),
("EIDRM", libc::EIDRM),
("EBADMSG", libc::EBADMSG),
("ENFILE", libc::ENFILE),
("ESPIPE", libc::ESPIPE),
("ENOLINK", libc::ENOLINK),
("ENETRESET", libc::ENETRESET),
("ETIMEDOUT", libc::ETIMEDOUT),
("ENOENT", libc::ENOENT),
("EEXIST", libc::EEXIST),
("EDQUOT", libc::EDQUOT),
("ENOSTR", libc::ENOSTR),
("EFAULT", libc::EFAULT),
("EFBIG", libc::EFBIG),
("ENOTCONN", libc::ENOTCONN),
("EDESTADDRREQ", libc::EDESTADDRREQ),
("ENOLCK", libc::ENOLCK),
("ECONNABORTED", libc::ECONNABORTED),
("ENETUNREACH", libc::ENETUNREACH),
("ESTALE", libc::ESTALE),
("ENOSR", libc::ENOSR),
("ENOMEM", libc::ENOMEM),
("ENOTSOCK", libc::ENOTSOCK),
("EMLINK", libc::EMLINK),
("ERANGE", libc::ERANGE),
("ECONNRESET", libc::ECONNRESET),
("EADDRINUSE", libc::EADDRINUSE),
#[cfg(not(target_os = "redox"))]
("ENOTSUP", libc::ENOTSUP),
("ENAMETOOLONG", libc::ENAMETOOLONG),
("ENOTTY", libc::ENOTTY),
("ESOCKTNOSUPPORT", libc::ESOCKTNOSUPPORT),
("ETIME", libc::ETIME),
("ETOOMANYREFS", libc::ETOOMANYREFS),
("EMFILE", libc::EMFILE),
("ETXTBSY", libc::ETXTBSY),
("EINPROGRESS", libc::EINPROGRESS),
("ENXIO", libc::ENXIO),
("ECANCELED", libc::ECANCELED),
("EOWNERDEAD", libc::EOWNERDEAD),
("ENOTRECOVERABLE", libc::ENOTRECOVERABLE),
];
macro_rules! e {
($name:ident) => {
(stringify!($name), errors::$name as _)
};
(cfg($($cfg:tt)*), $name:ident) => {
#[cfg($($cfg)*)]
(stringify!($name), errors::$name as _)
};
}
#[cfg(windows)]
#[cfg(any(unix, windows))]
const ERROR_CODES: &[(&str, i32)] = &[
("ENODEV", 19),
("WSAEHOSTUNREACH", 10065),
("ENOMSG", 122),
("ENODATA", 120),
("ENOSYS", 40),
("EPIPE", 32),
("EINVAL", 22),
("EOVERFLOW", 132),
("EINTR", 4),
("WSAEUSERS", 10068),
("ENOTEMPTY", 41),
("WSAENOBUFS", 10055),
("EPROTO", 134),
("WSAEREMOTE", 10071),
("ECHILD", 10),
("WSAELOOP", 10062),
("EXDEV", 18),
("E2BIG", 7),
("ESRCH", 3),
("WSAEMSGSIZE", 10040),
("WSAEAFNOSUPPORT", 10047),
("WSAEHOSTDOWN", 10064),
("WSAEPFNOSUPPORT", 10046),
("WSAENOPROTOOPT", 10042),
("EBUSY", 16),
("WSAEWOULDBLOCK", 10035),
("WSAEISCONN", 10056),
("WSAESHUTDOWN", 10058),
("EBADF", 9),
("EIO", 5),
("WSAEPROTOTYPE", 10041),
("ENOSPC", 28),
("ENOEXEC", 8),
("WSAEALREADY", 10037),
("WSAENETDOWN", 10050),
("EACCES", 13),
("EILSEQ", 42),
("ENOTDIR", 20),
("EPERM", 1),
("EDOM", 33),
("WSAECONNREFUSED", 10061),
("EISDIR", 21),
("WSAEPROTONOSUPPORT", 10043),
("EROFS", 30),
("WSAEADDRNOTAVAIL", 10049),
("EIDRM", 111),
("EBADMSG", 104),
("ENFILE", 23),
("ESPIPE", 29),
("ENOLINK", 121),
("WSAENETRESET", 10052),
("WSAETIMEDOUT", 10060),
("ENOENT", 2),
("EEXIST", 17),
("WSAEDQUOT", 10069),
("ENOSTR", 125),
("EFAULT", 14),
("EFBIG", 27),
("EDEADLOCK", 36),
("WSAENOTCONN", 10057),
("WSAEDESTADDRREQ", 10039),
("ENOLCK", 39),
("WSAECONNABORTED", 10053),
("WSAENETUNREACH", 10051),
("WSAESTALE", 10070),
("ENOSR", 124),
("ENOMEM", 12),
("WSAENOTSOCK", 10038),
("EMLINK", 31),
("ERANGE", 34),
("WSAECONNRESET", 10054),
("WSAEADDRINUSE", 10048),
("WSAEOPNOTSUPP", 10045),
("EAGAIN", 11),
("ENAMETOOLONG", 38),
("ENOTTY", 25),
("WSAESOCKTNOSUPPORT", 10044),
("ETIME", 137),
("WSAETOOMANYREFS", 10059),
("EMFILE", 24),
("ETXTBSY", 139),
("WSAEINPROGRESS", 10036),
("ENXIO", 6),
("WSAEMFILE", 10024),
("WSAVERNOTSUPPORTED", 10092),
("WSAEPROCLIM", 10067),
("WSAEFAULT", 10014),
("WSANOTINITIALISED", 10093),
("WSAENAMETOOLONG", 10063),
("WSAENOTEMPTY", 10066),
("WSAEACCES", 10013),
("WSABASEERR", 10000),
("WSAEBADF", 10009),
("WSAEDISCON", 10101),
("WSAEINTR", 10004),
("WSASYSNOTREADY", 10091),
("WSAEINVAL", 10022),
("ECANCELED", 105),
("EOWNERDEAD", 133),
("ENOTRECOVERABLE", 127),
("ENOTSUP", 129),
e!(ENODEV),
e!(EHOSTUNREACH),
e!(cfg(not(windows)), ENOMSG),
e!(cfg(not(windows)), ENODATA),
e!(cfg(not(windows)), ENOTBLK),
e!(ENOSYS),
e!(EPIPE),
e!(EINVAL),
e!(cfg(not(windows)), EOVERFLOW),
e!(EINTR),
e!(EUSERS),
e!(ENOTEMPTY),
e!(ENOBUFS),
e!(cfg(not(windows)), EPROTO),
e!(EREMOTE),
e!(ECHILD),
e!(ELOOP),
e!(EXDEV),
e!(E2BIG),
e!(ESRCH),
e!(EMSGSIZE),
e!(EAFNOSUPPORT),
e!(EHOSTDOWN),
e!(EPFNOSUPPORT),
e!(ENOPROTOOPT),
e!(EBUSY),
e!(EAGAIN),
e!(EISCONN),
e!(ESHUTDOWN),
e!(EBADF),
e!(cfg(not(windows)), EMULTIHOP),
e!(EIO),
e!(EPROTOTYPE),
e!(ENOSPC),
e!(ENOEXEC),
e!(EALREADY),
e!(ENETDOWN),
e!(EACCES),
e!(EILSEQ),
e!(ENOTDIR),
e!(EPERM),
e!(EDOM),
e!(ECONNREFUSED),
e!(EISDIR),
e!(EPROTONOSUPPORT),
e!(EROFS),
e!(EADDRNOTAVAIL),
e!(cfg(not(windows)), EIDRM),
e!(cfg(not(windows)), EBADMSG),
e!(ENFILE),
e!(ESPIPE),
e!(cfg(not(windows)), ENOLINK),
e!(ENETRESET),
e!(ETIMEDOUT),
e!(ENOENT),
e!(EEXIST),
e!(EDQUOT),
e!(cfg(not(windows)), ENOSTR),
e!(EFAULT),
e!(EFBIG),
e!(ENOTCONN),
e!(EDESTADDRREQ),
e!(ENOLCK),
e!(ECONNABORTED),
e!(ENETUNREACH),
e!(ESTALE),
e!(cfg(not(windows)), ENOSR),
e!(ENOMEM),
e!(ENOTSOCK),
e!(EMLINK),
e!(ERANGE),
e!(ECONNRESET),
e!(EADDRINUSE),
e!(cfg(not(any(target_os = "redox", windows))), ENOTSUP),
e!(ENAMETOOLONG),
e!(ENOTTY),
e!(ESOCKTNOSUPPORT),
e!(cfg(not(windows)), ETIME),
e!(ETOOMANYREFS),
e!(EMFILE),
e!(cfg(not(windows)), ETXTBSY),
e!(EINPROGRESS),
e!(ENXIO),
e!(ECANCELED),
e!(cfg(not(windows)), EOWNERDEAD),
e!(cfg(not(windows)), ENOTRECOVERABLE),
e!(cfg(windows), WSAEAFNOSUPPORT),
e!(cfg(windows), WSAEHOSTDOWN),
e!(cfg(windows), WSAEPFNOSUPPORT),
e!(cfg(windows), WSAENOPROTOOPT),
e!(cfg(windows), WSAEISCONN),
e!(cfg(windows), WSAESHUTDOWN),
e!(cfg(windows), WSAEINVAL),
e!(cfg(windows), WSAEBADF),
e!(cfg(windows), WSAENAMETOOLONG),
e!(cfg(windows), WSAEPROCLIM),
e!(cfg(windows), WSAEMFILE),
e!(cfg(windows), WSAEINPROGRESS),
e!(cfg(windows), WSAETOOMANYREFS),
e!(cfg(windows), WSAESOCKTNOSUPPORT),
e!(cfg(windows), WSAECONNRESET),
e!(cfg(windows), WSAENOTSOCK),
e!(cfg(windows), WSAECONNABORTED),
e!(cfg(windows), WSAENOTCONN),
e!(cfg(windows), WSAEDQUOT),
e!(cfg(windows), WSAENETRESET),
e!(cfg(windows), WSAEADDRNOTAVAIL),
e!(cfg(windows), WSAEPROTONOSUPPORT),
e!(cfg(windows), WSAECONNREFUSED),
e!(cfg(windows), WSAEALREADY),
e!(cfg(windows), WSAEPROTOTYPE),
e!(cfg(windows), WSAEWOULDBLOCK),
e!(cfg(windows), WSAEMSGSIZE),
e!(cfg(windows), WSAELOOP),
e!(cfg(windows), WSAEREMOTE),
e!(cfg(windows), WSAENOBUFS),
e!(cfg(windows), WSAEUSERS),
e!(cfg(windows), WSAEHOSTUNREACH),
e!(cfg(windows), WSAENETDOWN),
e!(cfg(windows), WSAETIMEDOUT),
e!(cfg(windows), WSAEDESTADDRREQ),
e!(cfg(windows), WSAENETUNREACH),
e!(cfg(windows), WSAESTALE),
e!(cfg(windows), WSAEADDRINUSE),
e!(cfg(windows), WSAEOPNOTSUPP),
e!(cfg(windows), WSAEFAULT),
e!(cfg(windows), WSAENOTEMPTY),
e!(cfg(windows), WSAEACCES),
e!(cfg(windows), WSAEDISCON),
e!(cfg(windows), WSAEINTR),
];
#[cfg(not(any(unix, windows)))]

View File

@@ -48,6 +48,8 @@ mod select;
pub mod signal;
#[cfg(not(target_arch = "wasm32"))]
mod subprocess;
#[cfg(windows)]
mod winapi;
#[cfg(not(target_arch = "wasm32"))]
mod zlib;
@@ -119,5 +121,11 @@ pub fn get_module_inits() -> HashMap<String, StdlibInitFunc> {
modules.insert("pwd".to_string(), Box::new(pwd::make_module));
}
// Windows-only
#[cfg(windows)]
{
modules.insert("_winapi".to_string(), Box::new(winapi::make_module));
}
modules
}

View File

@@ -21,6 +21,7 @@ use nix::pty::openpty;
#[cfg(unix)]
use nix::unistd::{self, Gid, Pid, Uid, Whence};
use super::errno::errors;
use crate::function::{IntoPyNativeFunc, OptionalArg, PyFuncArgs};
use crate::obj::objbytes::PyBytesRef;
use crate::obj::objdict::PyDictRef;
@@ -152,21 +153,21 @@ pub fn os_open(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
}
pub fn convert_io_error(vm: &VirtualMachine, err: io::Error) -> PyObjectRef {
let os_error = match err.kind() {
ErrorKind::NotFound => {
let exc_type = vm.ctx.exceptions.file_not_found_error.clone();
vm.new_exception(exc_type, err.to_string())
}
ErrorKind::PermissionDenied => {
let exc_type = vm.ctx.exceptions.permission_error.clone();
vm.new_exception(exc_type, err.to_string())
}
ErrorKind::AlreadyExists => {
let exc_type = vm.ctx.exceptions.file_exists_error.clone();
vm.new_exception(exc_type, err.to_string())
}
_ => vm.new_os_error(err.to_string()),
#[allow(unreachable_patterns)] // some errors are just aliases of each other
let exc_type = match err.kind() {
ErrorKind::NotFound => vm.ctx.exceptions.file_not_found_error.clone(),
ErrorKind::PermissionDenied => vm.ctx.exceptions.permission_error.clone(),
ErrorKind::AlreadyExists => vm.ctx.exceptions.file_exists_error.clone(),
ErrorKind::WouldBlock => vm.ctx.exceptions.blocking_io_error.clone(),
_ => match err.raw_os_error() {
Some(errors::EAGAIN)
| Some(errors::EALREADY)
| Some(errors::EWOULDBLOCK)
| Some(errors::EINPROGRESS) => vm.ctx.exceptions.blocking_io_error.clone(),
_ => vm.ctx.exceptions.os_error.clone(),
},
};
let os_error = vm.new_exception(exc_type, err.to_string());
if let Some(errno) = err.raw_os_error() {
vm.set_attr(&os_error, "errno", vm.ctx.new_int(errno))
.unwrap();
@@ -1089,6 +1090,17 @@ pub fn os_ttyname(fd: i32, vm: &VirtualMachine) -> PyResult {
}
}
fn os_urandom(size: usize, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
let mut buf = vec![0u8; size];
match getrandom::getrandom(&mut buf) {
Ok(()) => Ok(buf),
Err(e) => match e.raw_os_error() {
Some(errno) => Err(convert_io_error(vm, io::Error::from_raw_os_error(errno))),
None => Err(vm.new_os_error("Getting random failed".to_string())),
},
}
}
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
let ctx = &vm.ctx;
@@ -1213,6 +1225,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
"getpid" => ctx.new_rustfunc(os_getpid),
"cpu_count" => ctx.new_rustfunc(os_cpu_count),
"_exit" => ctx.new_rustfunc(os_exit),
"urandom" => ctx.new_rustfunc(os_urandom),
"O_RDONLY" => ctx.new_int(libc::O_RDONLY),
"O_WRONLY" => ctx.new_int(libc::O_WRONLY),

View File

@@ -135,6 +135,11 @@ fn select_select(
let (wlist, mut w) = seq2set(&wlist)?;
let (xlist, mut x) = seq2set(&xlist)?;
if rlist.is_empty() && wlist.is_empty() && xlist.is_empty() {
let empty = vm.ctx.new_list(vec![]);
return Ok((empty.clone(), empty.clone(), empty));
}
let nfds = [&mut r, &mut w, &mut x]
.iter_mut()
.filter_map(|set| set.highest())

View File

@@ -7,7 +7,7 @@ use byteorder::{BigEndian, ByteOrder};
use gethostname::gethostname;
#[cfg(all(unix, not(target_os = "redox")))]
use nix::unistd::sethostname;
use socket2::{Domain, Socket, Type as SocketType};
use socket2::{Domain, Protocol, Socket, Type as SocketType};
use super::os::convert_io_error;
#[cfg(unix)]
@@ -27,7 +27,31 @@ type RawSocket = std::os::unix::io::RawFd;
type RawSocket = std::os::windows::raw::SOCKET;
#[cfg(unix)]
use libc as c;
mod c {
pub use libc::*;
// TODO: open a PR to add these constants to libc; then just use libc
#[cfg(target_os = "android")]
pub const AI_PASSIVE: c_int = 0x00000001;
#[cfg(target_os = "android")]
pub const AI_CANONNAME: c_int = 0x00000002;
#[cfg(target_os = "android")]
pub const AI_NUMERICHOST: c_int = 0x00000004;
#[cfg(target_os = "android")]
pub const AI_NUMERICSERV: c_int = 0x00000008;
#[cfg(target_os = "android")]
pub const AI_MASK: c_int =
AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | AI_ADDRCONFIG;
#[cfg(target_os = "android")]
pub const AI_ALL: c_int = 0x00000100;
#[cfg(target_os = "android")]
pub const AI_V4MAPPED_CFG: c_int = 0x00000200;
#[cfg(target_os = "android")]
pub const AI_ADDRCONFIG: c_int = 0x00000400;
#[cfg(target_os = "android")]
pub const AI_V4MAPPED: c_int = 0x00000800;
#[cfg(target_os = "android")]
pub const AI_DEFAULT: c_int = AI_V4MAPPED_CFG | AI_ADDRCONFIG;
}
#[cfg(windows)]
mod c {
pub use winapi::shared::ws2def::*;
@@ -92,28 +116,17 @@ impl PySocket {
unsafe { Socket::from_raw_socket(fileno) }
}
} else {
let domain = match family {
c::AF_INET => Domain::ipv4(),
c::AF_INET6 => Domain::ipv6(),
#[cfg(unix)]
c::AF_UNIX => Domain::unix(),
_ => {
return Err(vm.new_os_error(format!("Unknown address family value: {}", family)))
}
};
let sock = Socket::new(
Domain::from(family),
SocketType::from(socket_kind),
Some(Protocol::from(proto)),
)
.map_err(|err| convert_sock_error(vm, err))?;
self.family.set(family);
let socket_type = match socket_kind {
c::SOCK_STREAM => SocketType::stream(),
c::SOCK_DGRAM => SocketType::dgram(),
_ => {
return Err(
vm.new_os_error(format!("Unknown socket kind value: {}", socket_kind))
)
}
};
self.kind.set(socket_kind);
self.proto.set(proto);
Socket::new(domain, socket_type, None).map_err(|err| convert_sock_error(vm, err))?
sock
};
self.sock.replace(sock);
Ok(())
@@ -435,6 +448,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
"error" => ctx.exceptions.os_error.clone(),
"timeout" => socket_timeout,
"gaierror" => socket_gaierror,
"AF_UNSPEC" => ctx.new_int(0),
"AF_INET" => ctx.new_int(c::AF_INET),
"AF_INET6" => ctx.new_int(c::AF_INET6),
"SOCK_STREAM" => ctx.new_int(c::SOCK_STREAM),
@@ -446,6 +460,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
"MSG_PEEK" => ctx.new_int(c::MSG_PEEK),
"MSG_WAITALL" => ctx.new_int(c::MSG_WAITALL),
"AI_ALL" => ctx.new_int(c::AI_ALL),
"AI_PASSIVE" => ctx.new_int(c::AI_PASSIVE),
"socket" => PySocket::make_class(ctx),
"inet_aton" => ctx.new_rustfunc(socket_inet_aton),
"inet_ntoa" => ctx.new_rustfunc(socket_inet_ntoa),

29
vm/src/stdlib/winapi.rs Normal file
View File

@@ -0,0 +1,29 @@
use std::io;
use winapi::shared::winerror;
use winapi::um::winnt::HANDLE;
use winapi::um::{handleapi, winbase};
use super::os::convert_io_error;
use crate::pyobject::{PyObjectRef, PyResult};
use crate::VirtualMachine;
fn winapi_CloseHandle(handle: usize, vm: &VirtualMachine) -> PyResult<()> {
let res = unsafe { handleapi::CloseHandle(handle as HANDLE) };
if res == 0 {
Err(convert_io_error(vm, io::Error::last_os_error()))
} else {
Ok(())
}
}
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
let ctx = &vm.ctx;
py_module!(vm, "_winapi", {
"CloseHandle" => ctx.new_rustfunc(winapi_CloseHandle),
"WAIT_OBJECT_0" => ctx.new_int(winbase::WAIT_OBJECT_0),
"WAIT_ABANDONED" => ctx.new_int(winbase::WAIT_ABANDONED),
"WAIT_ABANDONED_0" => ctx.new_int(winbase::WAIT_ABANDONED_0),
"WAIT_TIMEOUT" => ctx.new_int(winerror::WAIT_TIMEOUT),
"INFINITE" => ctx.new_int(winbase::INFINITE),
})
}

View File

@@ -580,9 +580,15 @@ impl VirtualMachine {
} else if let Some(PyMethod {
ref function,
ref object,
actually_bind,
}) = func_ref.payload()
{
self.invoke(&function, args.insert(object.clone()))
let args = if *actually_bind {
args.insert(object.clone())
} else {
args
};
self.invoke(&function, args)
} else if let Some(PyBuiltinFunction { ref value }) = func_ref.payload() {
value(self, args)
} else if self.is_callable(&func_ref) {
@@ -952,7 +958,7 @@ impl VirtualMachine {
}
let attr = if let Some(ref dict) = obj.dict {
dict.get_item_option(name_str.as_str(), self)?
dict.borrow().get_item_option(name_str.as_str(), self)?
} else {
None
};
@@ -1303,6 +1309,28 @@ impl VirtualMachine {
};
Ok(value)
}
#[doc(hidden)]
pub fn __module_set_attr(
&self,
module: &PyObjectRef,
attr_name: impl TryIntoRef<PyString>,
attr_value: impl Into<PyObjectRef>,
) -> PyResult<()> {
let val = attr_value.into();
let val = if val
.class()
.is(&self.ctx.types.builtin_function_or_method_type)
{
PyMethod::new_nobind(module.clone(), val)
.into_ref(self)
.into_object()
} else {
val
};
self.set_attr(module, attr_name, val)?;
Ok(())
}
}
impl Default for VirtualMachine {