Skip to content

Commit 012799f

Browse files
authored
Fix enum and os.read related to signal (#6552)
* fix enum * fix os.read to check signals
1 parent fd6c548 commit 012799f

File tree

7 files changed

+60
-34
lines changed

7 files changed

+60
-34
lines changed

Lib/test/test_descr.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4961,7 +4961,6 @@ class OverrideBoth(OverrideNew, OverrideInit):
49614961
self.assertRaises(TypeError, case, 1, 2, 3)
49624962
self.assertRaises(TypeError, case, 1, 2, foo=3)
49634963

4964-
@unittest.expectedFailure # TODO: RUSTPYTHON
49654964
def test_subclassing_does_not_duplicate_dict_descriptors(self):
49664965
class Base:
49674966
pass

Lib/test/test_file_eintr.py

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,6 @@ def _test_reading(self, data_to_write, read_and_verify_code):
152152
'"got data %r\\nexpected %r" % (got, expected))'
153153
)
154154

155-
@unittest.expectedFailure # TODO: RUSTPYTHON
156155
def test_readline(self):
157156
"""readline() must handle signals and not lose data."""
158157
self._test_reading(
@@ -161,7 +160,6 @@ def test_readline(self):
161160
read_method_name='readline',
162161
expected=b'hello, world!\n'))
163162

164-
@unittest.expectedFailure # TODO: RUSTPYTHON
165163
def test_readlines(self):
166164
"""readlines() must handle signals and not lose data."""
167165
self._test_reading(
@@ -170,7 +168,6 @@ def test_readlines(self):
170168
read_method_name='readlines',
171169
expected=[b'hello\n', b'world!\n']))
172170

173-
@unittest.expectedFailure # TODO: RUSTPYTHON
174171
def test_readall(self):
175172
"""readall() must handle signals and not lose data."""
176173
self._test_reading(
@@ -189,6 +186,19 @@ def test_readall(self):
189186
class CTestFileIOSignalInterrupt(TestFileIOSignalInterrupt, unittest.TestCase):
190187
modname = '_io'
191188

189+
# TODO: RUSTPYTHON - _io module uses _pyio internally, signal handling differs
190+
@unittest.expectedFailure
191+
def test_readline(self):
192+
super().test_readline()
193+
194+
@unittest.expectedFailure
195+
def test_readlines(self):
196+
super().test_readlines()
197+
198+
@unittest.expectedFailure
199+
def test_readall(self):
200+
super().test_readall()
201+
192202
class PyTestFileIOSignalInterrupt(TestFileIOSignalInterrupt, unittest.TestCase):
193203
modname = '_pyio'
194204

@@ -200,7 +210,6 @@ def _generate_infile_setup_code(self):
200210
'assert isinstance(infile, io.BufferedReader)' %
201211
self.modname)
202212

203-
@unittest.expectedFailure # TODO: RUSTPYTHON
204213
def test_readall(self):
205214
"""BufferedReader.read() must handle signals and not lose data."""
206215
self._test_reading(
@@ -212,6 +221,19 @@ def test_readall(self):
212221
class CTestBufferedIOSignalInterrupt(TestBufferedIOSignalInterrupt, unittest.TestCase):
213222
modname = '_io'
214223

224+
# TODO: RUSTPYTHON - _io module uses _pyio internally, signal handling differs
225+
@unittest.expectedFailure
226+
def test_readline(self):
227+
super().test_readline()
228+
229+
@unittest.expectedFailure
230+
def test_readlines(self):
231+
super().test_readlines()
232+
233+
@unittest.expectedFailure
234+
def test_readall(self):
235+
super().test_readall()
236+
215237
class PyTestBufferedIOSignalInterrupt(TestBufferedIOSignalInterrupt, unittest.TestCase):
216238
modname = '_pyio'
217239

@@ -224,7 +246,6 @@ def _generate_infile_setup_code(self):
224246
'assert isinstance(infile, io.TextIOWrapper)' %
225247
self.modname)
226248

227-
@unittest.expectedFailure # TODO: RUSTPYTHON
228249
def test_readline(self):
229250
"""readline() must handle signals and not lose data."""
230251
self._test_reading(
@@ -233,7 +254,6 @@ def test_readline(self):
233254
read_method_name='readline',
234255
expected='hello, world!\n'))
235256

236-
@unittest.expectedFailure # TODO: RUSTPYTHON
237257
def test_readlines(self):
238258
"""readlines() must handle signals and not lose data."""
239259
self._test_reading(
@@ -242,7 +262,6 @@ def test_readlines(self):
242262
read_method_name='readlines',
243263
expected=['hello\n', 'world!\n']))
244264

245-
@unittest.expectedFailure # TODO: RUSTPYTHON
246265
def test_readall(self):
247266
"""read() must handle signals and not lose data."""
248267
self._test_reading(
@@ -254,6 +273,19 @@ def test_readall(self):
254273
class CTestTextIOSignalInterrupt(TestTextIOSignalInterrupt, unittest.TestCase):
255274
modname = '_io'
256275

276+
# TODO: RUSTPYTHON - _io module uses _pyio internally, signal handling differs
277+
@unittest.expectedFailure
278+
def test_readline(self):
279+
super().test_readline()
280+
281+
@unittest.expectedFailure
282+
def test_readlines(self):
283+
super().test_readlines()
284+
285+
@unittest.expectedFailure
286+
def test_readall(self):
287+
super().test_readall()
288+
257289
class PyTestTextIOSignalInterrupt(TestTextIOSignalInterrupt, unittest.TestCase):
258290
modname = '_pyio'
259291

Lib/test/test_signal.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424

2525
class GenericTests(unittest.TestCase):
2626

27-
# TODO: RUSTPYTHON
28-
@unittest.expectedFailure
2927
def test_enums(self):
3028
for name in dir(signal):
3129
sig = getattr(signal, name)
@@ -763,17 +761,13 @@ def handler(signum, frame):
763761
% (exitcode, stdout))
764762
return (exitcode == 3)
765763

766-
# TODO: RUSTPYTHON
767-
@unittest.expectedFailure
768764
def test_without_siginterrupt(self):
769765
# If a signal handler is installed and siginterrupt is not called
770766
# at all, when that signal arrives, it interrupts a syscall that's in
771767
# progress.
772768
interrupted = self.readpipe_interrupted(None)
773769
self.assertTrue(interrupted)
774770

775-
# TODO: RUSTPYTHON
776-
@unittest.expectedFailure
777771
def test_siginterrupt_on(self):
778772
# If a signal handler is installed and siginterrupt is called with
779773
# a true value for the second argument, when that signal arrives, it

Lib/test/test_socket.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2052,8 +2052,6 @@ def test_socket_fileno_requires_socket_fd(self):
20522052
fileno=afile.fileno())
20532053
self.assertEqual(cm.exception.errno, errno.ENOTSOCK)
20542054

2055-
# TODO: RUSTPYTHON
2056-
@unittest.expectedFailure
20572055
def test_addressfamily_enum(self):
20582056
import _socket, enum
20592057
CheckedAddressFamily = enum._old_convert_(
@@ -2063,8 +2061,6 @@ def test_addressfamily_enum(self):
20632061
)
20642062
enum._test_simple_enum(CheckedAddressFamily, socket.AddressFamily)
20652063

2066-
# TODO: RUSTPYTHON
2067-
@unittest.expectedFailure
20682064
def test_socketkind_enum(self):
20692065
import _socket, enum
20702066
CheckedSocketKind = enum._old_convert_(
@@ -2074,8 +2070,6 @@ def test_socketkind_enum(self):
20742070
)
20752071
enum._test_simple_enum(CheckedSocketKind, socket.SocketKind)
20762072

2077-
# TODO: RUSTPYTHON
2078-
@unittest.expectedFailure
20792073
def test_msgflag_enum(self):
20802074
import _socket, enum
20812075
CheckedMsgFlag = enum._old_convert_(
@@ -2085,8 +2079,6 @@ def test_msgflag_enum(self):
20852079
)
20862080
enum._test_simple_enum(CheckedMsgFlag, socket.MsgFlag)
20872081

2088-
# TODO: RUSTPYTHON
2089-
@unittest.expectedFailure
20902082
def test_addressinfo_enum(self):
20912083
import _socket, enum
20922084
CheckedAddressInfo = enum._old_convert_(

Lib/test/test_ssl.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5477,7 +5477,6 @@ class Checked_TLSMessageType(enum.IntEnum):
54775477
CHANGE_CIPHER_SPEC = 0x0101
54785478
enum._test_simple_enum(Checked_TLSMessageType, _TLSMessageType)
54795479

5480-
@unittest.expectedFailure # TODO: RUSTPYTHON
54815480
def test_sslmethod(self):
54825481
Checked_SSLMethod = enum._old_convert_(
54835482
enum.IntEnum, '_SSLMethod', 'ssl',
@@ -5488,7 +5487,6 @@ def test_sslmethod(self):
54885487
Checked_SSLMethod.PROTOCOL_SSLv23 = Checked_SSLMethod.PROTOCOL_TLS
54895488
enum._test_simple_enum(Checked_SSLMethod, ssl._SSLMethod)
54905489

5491-
@unittest.expectedFailure # TODO: RUSTPYTHON
54925490
def test_options(self):
54935491
CheckedOptions = enum._old_convert_(
54945492
enum.IntFlag, 'Options', 'ssl',
@@ -5497,7 +5495,6 @@ def test_options(self):
54975495
)
54985496
enum._test_simple_enum(CheckedOptions, ssl.Options)
54995497

5500-
@unittest.expectedFailure # TODO: RUSTPYTHON
55015498
def test_alertdescription(self):
55025499
CheckedAlertDescription = enum._old_convert_(
55035500
enum.IntEnum, 'AlertDescription', 'ssl',
@@ -5506,7 +5503,6 @@ def test_alertdescription(self):
55065503
)
55075504
enum._test_simple_enum(CheckedAlertDescription, ssl.AlertDescription)
55085505

5509-
@unittest.expectedFailure # TODO: RUSTPYTHON
55105506
def test_sslerrornumber(self):
55115507
Checked_SSLErrorNumber = enum._old_convert_(
55125508
enum.IntEnum, 'SSLErrorNumber', 'ssl',
@@ -5515,7 +5511,6 @@ def test_sslerrornumber(self):
55155511
)
55165512
enum._test_simple_enum(Checked_SSLErrorNumber, ssl.SSLErrorNumber)
55175513

5518-
@unittest.expectedFailure # TODO: RUSTPYTHON
55195514
def test_verifyflags(self):
55205515
CheckedVerifyFlags = enum._old_convert_(
55215516
enum.IntFlag, 'VerifyFlags', 'ssl',
@@ -5524,7 +5519,6 @@ def test_verifyflags(self):
55245519
)
55255520
enum._test_simple_enum(CheckedVerifyFlags, ssl.VerifyFlags)
55265521

5527-
@unittest.expectedFailure # TODO: RUSTPYTHON
55285522
def test_verifymode(self):
55295523
CheckedVerifyMode = enum._old_convert_(
55305524
enum.IntEnum, 'VerifyMode', 'ssl',

crates/vm/src/builtins/type.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1499,9 +1499,15 @@ impl Constructor for PyType {
14991499
// Only add if:
15001500
// 1. base is not type (type subclasses inherit __dict__ from type)
15011501
// 2. the class has HAS_DICT flag (i.e., __slots__ was not defined or __dict__ is in __slots__)
1502+
// 3. no base class in MRO already provides __dict__ descriptor
15021503
if !base_is_type && typ.slots.flags.has_feature(PyTypeFlags::HAS_DICT) {
15031504
let __dict__ = identifier!(vm, __dict__);
1504-
if !typ.attributes.read().contains_key(&__dict__) {
1505+
let has_inherited_dict = typ
1506+
.mro
1507+
.read()
1508+
.iter()
1509+
.any(|base| base.attributes.read().contains_key(&__dict__));
1510+
if !typ.attributes.read().contains_key(&__dict__) && !has_inherited_dict {
15051511
unsafe {
15061512
let descriptor =
15071513
vm.ctx

crates/vm/src/stdlib/os.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -274,12 +274,21 @@ pub(super) mod _os {
274274
}
275275

276276
#[pyfunction]
277-
fn read(fd: crt_fd::Borrowed<'_>, n: usize, vm: &VirtualMachine) -> io::Result<PyBytesRef> {
277+
fn read(fd: crt_fd::Borrowed<'_>, n: usize, vm: &VirtualMachine) -> PyResult<PyBytesRef> {
278278
let mut buffer = vec![0u8; n];
279-
let n = crt_fd::read(fd, &mut buffer)?;
280-
buffer.truncate(n);
281-
282-
Ok(vm.ctx.new_bytes(buffer))
279+
loop {
280+
match crt_fd::read(fd, &mut buffer) {
281+
Ok(n) => {
282+
buffer.truncate(n);
283+
return Ok(vm.ctx.new_bytes(buffer));
284+
}
285+
Err(e) if e.raw_os_error() == Some(libc::EINTR) => {
286+
vm.check_signals()?;
287+
continue;
288+
}
289+
Err(e) => return Err(e.into_pyexception(vm)),
290+
}
291+
}
283292
}
284293

285294
#[pyfunction]

0 commit comments

Comments
 (0)