mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Use ordinary fileno lookup in select (#9266)
* Use ordinary fileno lookup in select Assisted-by: Codex:GPT-6 * Share select descriptor conversion Assisted-by: Codex:GPT-6
This commit is contained in:
1 parent
6f2d4a203d
commit
02f4fbbb62
2 files changed
+48
-9
No files matched your search
@@ -3,7 +3,8 @@
|
||||
pub(crate) use decl::module_def;
|
||||
|
||||
use crate::vm::{
|
||||
PyObject, PyObjectRef, PyResult, TryFromObject, VirtualMachine, builtins::PyListRef,
|
||||
PyObject, PyObjectRef, PyResult, TryFromObject, VirtualMachine,
|
||||
builtins::{PyInt, PyListRef},
|
||||
};
|
||||
use rustpython_host_env::select::{self as host_select, FdSet, RawFd, platform::FD_SETSIZE};
|
||||
use std::io;
|
||||
@@ -17,14 +18,20 @@ struct Selectable {
|
||||
|
||||
impl TryFromObject for Selectable {
|
||||
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
|
||||
let fno = obj.try_to_value(vm).or_else(|_| {
|
||||
let meth = vm.get_method_or_type_error(
|
||||
obj.clone(),
|
||||
vm.ctx.interned_str("fileno").unwrap(),
|
||||
|| "select arg must be an int or object with a fileno() method".to_owned(),
|
||||
)?;
|
||||
meth.call((), vm)?.try_into_value(vm)
|
||||
})?;
|
||||
let fileno;
|
||||
let fd = if let Some(fd) = obj.downcast_ref::<PyInt>() {
|
||||
fd
|
||||
} else {
|
||||
let meth = vm.get_attribute_opt(&obj, "fileno")?.ok_or_else(|| {
|
||||
vm.new_type_error("select arg must be an int or object with a fileno() method")
|
||||
})?;
|
||||
fileno = meth
|
||||
.call((), vm)?
|
||||
.downcast::<PyInt>()
|
||||
.map_err(|_| vm.new_type_error("fileno() returned a non-integer"))?;
|
||||
&fileno
|
||||
};
|
||||
let fno = fd.try_to_primitive(vm)?;
|
||||
Ok(Self { obj, fno })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,3 +167,35 @@ if hasattr(select, "poll") and hasattr(signal, "setitimer"):
|
||||
assert handled == [signal.SIGALRM], handled
|
||||
idle.close()
|
||||
idle_peer.close()
|
||||
|
||||
|
||||
# fileno is an ordinary attribute, not a special method.
|
||||
class InstanceFileno:
|
||||
pass
|
||||
|
||||
|
||||
class DynamicFileno:
|
||||
def __getattr__(self, name):
|
||||
if name == "fileno":
|
||||
return lookup_reader.fileno
|
||||
raise AttributeError(name)
|
||||
|
||||
|
||||
class IndexOnly:
|
||||
def __index__(self):
|
||||
return lookup_reader.fileno()
|
||||
|
||||
|
||||
lookup_reader, lookup_writer = socket.socketpair()
|
||||
try:
|
||||
lookup_writer.send(b"x")
|
||||
instance = InstanceFileno()
|
||||
instance.fileno = lookup_reader.fileno
|
||||
for obj in (instance, DynamicFileno()):
|
||||
assert select.select([obj], [], [], 0) == ([obj], [], [])
|
||||
assert_raises(TypeError, select.select, [IndexOnly()], [], [], 0)
|
||||
instance.fileno = IndexOnly
|
||||
assert_raises(TypeError, select.select, [instance], [], [], 0)
|
||||
finally:
|
||||
lookup_reader.close()
|
||||
lookup_writer.close()
|
||||
Reference in new issue
Block a user