diff --git a/crates/derive-impl/src/pyclass.rs b/crates/derive-impl/src/pyclass.rs index 1fec51ddd42..d4590c6c4d3 100644 --- a/crates/derive-impl/src/pyclass.rs +++ b/crates/derive-impl/src/pyclass.rs @@ -917,7 +917,7 @@ where ("__new__", "Constructor"), ("__init__", "Initializer"), // Representable trait - // ("__repr__", "Representable"), + ("__repr__", "Representable"), // ("__str__", "???"), // allow __str__ // Hashable trait ("__hash__", "Hashable"), @@ -927,9 +927,9 @@ where // NOTE: __getattribute__, __setattr__, __delattr__ are intentionally NOT forbidden // because they need pymethod for subclass override mechanism to work properly. // GetDescriptor/SetDescriptor traits - // ("__get__", "GetDescriptor"), - // ("__set__", "SetDescriptor"), - // ("__delete__", "SetDescriptor"), + ("__get__", "GetDescriptor"), + ("__set__", "SetDescriptor"), + ("__delete__", "SetDescriptor"), // AsNumber trait ("__add__", "AsNumber"), ("__radd__", "AsNumber"), @@ -981,15 +981,15 @@ where ("__index__", "AsNumber"), ("__bool__", "AsNumber"), // AsSequence trait - // ("__len__", "AsSequence (or AsMapping)"), - // ("__contains__", "AsSequence"), + ("__len__", "AsSequence (or AsMapping)"), + ("__contains__", "AsSequence"), // AsMapping trait - // ("__getitem__", "AsMapping (or AsSequence)"), - // ("__setitem__", "AsMapping (or AsSequence)"), - // ("__delitem__", "AsMapping (or AsSequence)"), - // IterNext trait - // ("__iter__", "IterNext"), - // ("__next__", "IterNext"), + ("__getitem__", "AsMapping (or AsSequence)"), + ("__setitem__", "AsMapping (or AsSequence)"), + ("__delitem__", "AsMapping (or AsSequence)"), + // Iterable/IterNext traits + ("__iter__", "Iterable"), + ("__next__", "IterNext"), // Comparable trait ("__eq__", "Comparable"), ("__ne__", "Comparable"), diff --git a/crates/stdlib/src/_asyncio.rs b/crates/stdlib/src/_asyncio.rs index 8b32e4625da..afa372cffe6 100644 --- a/crates/stdlib/src/_asyncio.rs +++ b/crates/stdlib/src/_asyncio.rs @@ -764,11 +764,6 @@ pub(crate) mod _asyncio { Ok(()) } - #[pymethod] - fn __iter__(zelf: PyRef, vm: &VirtualMachine) -> PyResult { - Self::__await__(zelf, vm) - } - #[pymethod] fn __await__(zelf: PyRef, _vm: &VirtualMachine) -> PyResult { Ok(PyFutureIter { @@ -1828,13 +1823,6 @@ pub(crate) mod _asyncio { } } - #[pymethod] - fn __iter__(zelf: PyRef, _vm: &VirtualMachine) -> PyResult { - Ok(PyFutureIter { - future: PyRwLock::new(Some(zelf.into())), - }) - } - #[pymethod] fn __await__(zelf: PyRef, _vm: &VirtualMachine) -> PyResult { Ok(PyFutureIter { diff --git a/crates/stdlib/src/socket.rs b/crates/stdlib/src/socket.rs index cecfbed4298..d3fe59144ef 100644 --- a/crates/stdlib/src/socket.rs +++ b/crates/stdlib/src/socket.rs @@ -20,7 +20,7 @@ mod _socket { ArgBytesLike, ArgIntoFloat, ArgMemoryBuffer, ArgStrOrBytesLike, Either, FsPath, OptionalArg, OptionalOption, }, - types::{Constructor, DefaultConstructor, Initializer, Representable}, + types::{Constructor, DefaultConstructor, Destructor, Initializer, Representable}, utils::ToCString, }; @@ -1417,7 +1417,44 @@ mod _socket { } } - #[pyclass(with(Constructor, Initializer, Representable), flags(BASETYPE))] + impl Destructor for PySocket { + fn del(zelf: &Py, vm: &VirtualMachine) -> PyResult<()> { + // Emit ResourceWarning if socket is still open + if zelf.sock.read().is_some() { + let laddr = if let Ok(sock) = zelf.sock() + && let Ok(addr) = sock.local_addr() + && let Ok(repr) = get_addr_tuple(&addr, vm).repr(vm) + { + format!(", laddr={}", repr.as_wtf8()) + } else { + String::new() + }; + + let msg = format!( + "unclosed ", + zelf.fileno(), + zelf.family.load(), + zelf.kind.load(), + zelf.proto.load(), + laddr + ); + let _ = crate::vm::warn::warn( + vm.ctx.new_str(msg).into(), + Some(vm.ctx.exceptions.resource_warning.to_owned()), + 1, + None, + vm, + ); + } + let _ = zelf.close(); + Ok(()) + } + } + + #[pyclass( + with(Constructor, Initializer, Representable, Destructor), + flags(BASETYPE) + )] impl PySocket { fn _init( zelf: PyRef, @@ -2139,38 +2176,6 @@ mod _socket { Ok(()) } - #[pymethod] - fn __del__(&self, vm: &VirtualMachine) { - // Emit ResourceWarning if socket is still open - if self.sock.read().is_some() { - let laddr = if let Ok(sock) = self.sock() - && let Ok(addr) = sock.local_addr() - && let Ok(repr) = get_addr_tuple(&addr, vm).repr(vm) - { - format!(", laddr={}", repr.as_wtf8()) - } else { - String::new() - }; - - let msg = format!( - "unclosed ", - self.fileno(), - self.family.load(), - self.kind.load(), - self.proto.load(), - laddr - ); - let _ = crate::vm::warn::warn( - vm.ctx.new_str(msg).into(), - Some(vm.ctx.exceptions.resource_warning.to_owned()), - 1, - None, - vm, - ); - } - let _ = self.close(); - } - #[pymethod] #[inline] fn detach(&self) -> i64 { diff --git a/crates/stdlib/src/ssl.rs b/crates/stdlib/src/ssl.rs index 17a514c9245..06c0010a79d 100644 --- a/crates/stdlib/src/ssl.rs +++ b/crates/stdlib/src/ssl.rs @@ -857,18 +857,13 @@ mod _ssl { binary_form: OptionalArg, } - #[pyclass(with(Constructor), flags(BASETYPE))] + #[pyclass(with(Constructor, Representable), flags(BASETYPE))] impl PySSLContext { // Helper method to convert DER certificate bytes to Python dict fn cert_der_to_dict(&self, vm: &VirtualMachine, cert_der: &[u8]) -> PyResult { cert::cert_der_to_dict_helper(vm, cert_der) } - #[pymethod] - fn __repr__(&self) -> String { - format!("", self.protocol) - } - #[pygetset] fn check_hostname(&self) -> bool { *self.check_hostname.read() @@ -2191,6 +2186,13 @@ mod _ssl { } } + impl Representable for PySSLContext { + #[inline] + fn repr_str(zelf: &Py, _vm: &VirtualMachine) -> PyResult { + Ok(format!("", zelf.protocol)) + } + } + impl Constructor for PySSLContext { type Args = (i32,); @@ -2374,7 +2376,7 @@ mod _ssl { Completed, // unwrap() completed successfully } - #[pyclass(with(Constructor), flags(BASETYPE))] + #[pyclass(with(Constructor, Representable), flags(BASETYPE))] impl PySSLSocket { // Check if this is BIO mode pub(crate) fn is_bio_mode(&self) -> bool { @@ -3021,11 +3023,6 @@ mod _ssl { } } - #[pymethod] - fn __repr__(&self) -> String { - "".to_string() - } - // Helper function to convert Python PROTO_* constants to rustls versions fn get_rustls_versions( minimum: i32, @@ -4562,6 +4559,13 @@ mod _ssl { } } + impl Representable for PySSLSocket { + #[inline] + fn repr_str(_zelf: &Py, _vm: &VirtualMachine) -> PyResult { + Ok("".to_owned()) + } + } + impl Constructor for PySSLSocket { type Args = (); diff --git a/crates/vm/src/builtins/str.rs b/crates/vm/src/builtins/str.rs index 8e98fc6e5c4..d882fa913a5 100644 --- a/crates/vm/src/builtins/str.rs +++ b/crates/vm/src/builtins/str.rs @@ -663,7 +663,6 @@ impl PyStr { self.data.is_empty() } - #[pymethod(name = "__len__")] #[inline] pub fn char_len(&self) -> usize { self.data.char_len()