GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Merge main after exception setter dependency landed · youknowdot/RustPython@3c4358a

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
  • Lib/test
    • test_atexit.py
    • test_frame.py
    • test_long.py
    • test_os
      • test_os.py
    • test_pyexpat.py
    • test_regrtest.py
    • test_socket.py
  • crates
    • common/src
      • int.rs
    • derive-impl/src
      • from_args.rs
    • derive/src
      • lib.rs
    • host_env/src
      • os.rs
      • socket.rs
      • time.rs
      • winreg.rs
    • stdlib/src
      • array.rs
      • csv.rs
      • elementtree.rs
      • json.rs
      • multiprocessing.rs
      • overlapped.rs
      • pickle.rs
      • pyexpat.rs
      • pystruct.rs
      • random.rs
      • select.rs
      • socket.rs
      • unicodedata.rs
    • vm/src
      • buffer.rs
      • builtins
        • bytearray.rs
        • dict.rs
        • function.rs
        • property.rs
        • range.rs
        • sentinel.rs
        • slice.rs
        • traceback.rs
      • coroutine.rs
      • exceptions.rs
      • function
        • argument.rs
        • getargs.rs
        • mod.rs
      • object
        • core.rs
      • stdlib
        • _codecs.rs
        • _ctypes.rs
        • _ctypes
          • function.rs
        • _functools.rs
        • _imp.rs
        • _interpchannels.rs
        • _interpreters.rs
        • _lsprof.rs
        • _signal.rs
        • _sre.rs
        • _thread.rs
        • _winapi.rs
        • builtins.rs
        • itertools.rs
        • nt.rs
        • os.rs
        • posix.rs
        • time.rs
        • winreg.rs
      • vm
        • interpreter.rs
        • thread.rs
      • windows.rs
  • scripts
    • whats_left.py

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Dismiss banner
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎Lib/test/test_atexit.py‎

Copy file name to clipboardExpand all lines: Lib/test/test_atexit.py
+57-1Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
import subprocess
44
import textwrap
55
import unittest
6-
from test.support import os_helper
76
from test import support
87
from test.support import SuppressCrashReport, script_helper
8+
from test.support import os_helper
99
from test.support import threading_helper
1010

1111
class GeneralTest(unittest.TestCase):
@@ -82,6 +82,62 @@ def thready():
8282
# want them to affect the rest of the tests.
8383
script_helper.assert_python_ok("-c", textwrap.dedent(source))
8484

85+
@threading_helper.requires_working_threading()
86+
def test_thread_created_in_atexit(self):
87+
source = """if True:
88+
import atexit
89+
import threading
90+
import time
91+
92+
93+
def run():
94+
print(24)
95+
time.sleep(1)
96+
print(42)
97+
98+
@atexit.register
99+
def start_thread():
100+
threading.Thread(target=run).start()
101+
"""
102+
return_code, stdout, stderr = script_helper.assert_python_ok("-c", source)
103+
self.assertEqual(return_code, 0)
104+
self.assertEqual(stdout, f"24{os.linesep}42{os.linesep}".encode("utf-8"))
105+
self.assertEqual(stderr, b"")
106+
107+
@threading_helper.requires_working_threading()
108+
@unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
109+
def test_thread_created_in_atexit_subinterpreter(self):
110+
try:
111+
from concurrent import interpreters
112+
except ImportError:
113+
self.skipTest("subinterpreters are not available")
114+
115+
read, write = os.pipe()
116+
source = f"""if True:
117+
import atexit
118+
import threading
119+
import time
120+
import os
121+
122+
def run():
123+
os.write({write}, b'spanish')
124+
time.sleep(1)
125+
os.write({write}, b'inquisition')
126+
127+
@atexit.register
128+
def start_thread():
129+
threading.Thread(target=run).start()
130+
"""
131+
interp = interpreters.create()
132+
try:
133+
interp.exec(source)
134+
135+
# Close the interpreter to invoke atexit callbacks
136+
interp.close()
137+
self.assertEqual(os.read(read, 100), b"spanishinquisition")
138+
finally:
139+
os.close(read)
140+
os.close(write)
85141

86142
@support.cpython_only
87143
class SubinterpreterTest(unittest.TestCase):
Collapse file

‎Lib/test/test_frame.py‎

Copy file name to clipboardExpand all lines: Lib/test/test_frame.py
-1Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,6 @@ def run(self):
776776
)
777777
sneaky_frame_object = sneaky_frame_object.f_back
778778

779-
@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: 'NoneType' object has no attribute 'exc_type'
780779
def test_entry_frames_are_invisible_during_teardown(self):
781780
class C:
782781
"""A weakref'able class."""
Collapse file

‎Lib/test/test_long.py‎

Copy file name to clipboardExpand all lines: Lib/test/test_long.py
-1Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,6 @@ def check_float_conversion(self, n):
403403
"Got {}, expected {}.".format(n, actual, expected))
404404
self.assertEqual(actual, expected, msg)
405405

406-
@unittest.expectedFailure # TODO: RUSTPYTHON
407406
@support.requires_IEEE_754
408407
def test_float_conversion(self):
409408

Collapse file

‎Lib/test/test_os/test_os.py‎

Copy file name to clipboardExpand all lines: Lib/test/test_os/test_os.py
-1Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2727,7 +2727,6 @@ def test_execve_invalid_env(self):
27272727

27282728
# See https://github.com/python/cpython/issues/137934 and the other
27292729
# related issues for the reason why we cannot test this on Windows.
2730-
@unittest.expectedFailure # TODO: RUSTPYTHON; TypeError: MyEnv.__getitem__() takes 1 positional argument but 2 were given
27312730
@unittest.skipIf(os.name == "nt", "POSIX-specific test")
27322731
@unittest.skipUnless(unix_shell and os.path.exists(unix_shell),
27332732
"requires a shell")
Collapse file

‎Lib/test/test_pyexpat.py‎

Copy file name to clipboardExpand all lines: Lib/test/test_pyexpat.py
-1Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,6 @@ def test_legal(self):
407407
expat.ParserCreate(namespace_separator=None)
408408
expat.ParserCreate(namespace_separator=' ')
409409

410-
@unittest.expectedFailure # TODO: RUSTPYTHON
411410
def test_illegal(self):
412411
with self.assertRaisesRegex(TypeError,
413412
r"ParserCreate\(\) argument (2|'namespace_separator') "
Collapse file

‎Lib/test/test_regrtest.py‎

Copy file name to clipboardExpand all lines: Lib/test/test_regrtest.py
-1Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1902,7 +1902,6 @@ def test_sleep(self):
19021902
self.assertRegex(output,
19031903
re.compile('%s timed out' % testname, re.MULTILINE))
19041904

1905-
@unittest.expectedFailure # TODO: RUSTPYTHON; test_unraisable_exc (test_regrtest_noop39.Tests.test_unraisable_exc) ... ok
19061905
def test_unraisable_exc(self):
19071906
# --fail-env-changed must catch unraisable exception.
19081907
# The exception must be displayed even if sys.stderr is redirected.
Collapse file

‎Lib/test/test_socket.py‎

Copy file name to clipboardExpand all lines: Lib/test/test_socket.py
-5Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7160,7 +7160,6 @@ def create_alg(self, typ, name):
71607160

71617161
# bpo-31705: On kernel older than 4.5, sendto() failed with ENOKEY,
71627162
# at least on ppc64le architecture
7163-
@unittest.expectedFailure # TODO: RUSTPYTHON; - AF_ALG not fully implemented
71647163
@support.requires_linux_version(4, 5)
71657164
def test_sha256(self):
71667165
expected = bytes.fromhex("ba7816bf8f01cfea414140de5dae2223b00361a396"
@@ -7179,7 +7178,6 @@ def test_sha256(self):
71797178
op.send(b'')
71807179
self.assertEqual(op.recv(512), expected)
71817180

7182-
@unittest.expectedFailure # TODO: RUSTPYTHON; - AF_ALG not fully implemented
71837181
def test_hmac_sha1(self):
71847182
# gh-109396: In FIPS mode, Linux 6.5 requires a key
71857183
# of at least 112 bits. Use a key of 152 bits.
@@ -7195,7 +7193,6 @@ def test_hmac_sha1(self):
71957193

71967194
# Although it should work with 3.19 and newer the test blocks on
71977195
# Ubuntu 15.10 with Kernel 4.2.0-19.
7198-
@unittest.expectedFailure # TODO: RUSTPYTHON; - AF_ALG not fully implemented
71997196
@support.requires_linux_version(4, 3)
72007197
def test_aes_cbc(self):
72017198
key = bytes.fromhex('06a9214036b8a15b512e03d534120006')
@@ -7237,7 +7234,6 @@ def test_aes_cbc(self):
72377234
self.assertEqual(len(dec), msglen * multiplier)
72387235
self.assertEqual(dec, msg * multiplier)
72397236

7240-
@unittest.expectedFailure # TODO: RUSTPYTHON; - AF_ALG not fully implemented
72417237
@support.requires_linux_version(4, 9) # see gh-73510
72427238
def test_aead_aes_gcm(self):
72437239
kernel_version = support._get_kernel_version("Linux")
@@ -7307,7 +7303,6 @@ def test_aead_aes_gcm(self):
73077303
res = op.recv(len(msg) - taglen)
73087304
self.assertEqual(plain, res[assoclen:])
73097305

7310-
@unittest.expectedFailure # TODO: RUSTPYTHON; - AF_ALG not fully implemented
73117306
@support.requires_linux_version(4, 3) # see test_aes_cbc
73127307
def test_drbg_pr_sha256(self):
73137308
# deterministic random bit generator, prediction resistance, sha256
Collapse file

‎crates/common/src/int.rs‎

Copy file name to clipboardExpand all lines: crates/common/src/int.rs
+11-9Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,10 @@ use num_traits::{One, ToPrimitive, Zero};
66
#[must_use]
77
pub fn true_div(numerator: &BigInt, denominator: &BigInt) -> f64 {
88
let rational = Rational::from_integers_ref(numerator.into(), denominator.into());
9-
match rational.rounding_into(RoundingMode::Nearest) {
10-
// returned value is $t::MAX but still less than the original
11-
(val, core::cmp::Ordering::Less) if val == f64::MAX => f64::INFINITY,
12-
// returned value is $t::MIN but still greater than the original
13-
(val, core::cmp::Ordering::Greater) if val == f64::MIN => f64::NEG_INFINITY,
14-
(val, _) => val,
15-
}
9+
// Nearest rounding can return the largest finite value for a quotient
10+
// slightly beyond it; overflow starts at the halfway rounding boundary.
11+
let (rounded, _) = rational.rounding_into(RoundingMode::Nearest);
12+
rounded
1613
}
1714

1815
#[must_use]
@@ -202,11 +199,16 @@ fn word_all_ascii_digits(word: u64) -> bool {
202199
(below | above) & 0x8080_8080_8080_8080 == 0
203200
}
204201

205-
// num-bigint now returns Some(inf) for to_f64() in some cases, so just keep that the same for now
202+
/// Convert an integer to a finite float, or return None when it overflows.
206203
#[inline(always)]
207204
#[must_use]
208205
pub fn bigint_to_finite_float(int: &BigInt) -> Option<f64> {
209-
int.to_f64().filter(|f| f.is_finite())
206+
// malachite-bigint's ToPrimitive returns None when the input exceeds
207+
// the largest finite magnitude, even when nearest rounding is finite.
208+
let value = int
209+
.to_f64()
210+
.unwrap_or_else(|| true_div(int, &BigInt::one()));
211+
value.is_finite().then_some(value)
210212
}
211213

212214
#[cfg(test)]
Collapse file

‎crates/derive-impl/src/from_args.rs‎

Copy file name to clipboardExpand all lines: crates/derive-impl/src/from_args.rs
+70Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,3 +657,73 @@ pub(crate) fn impl_from_args(input: DeriveInput) -> Result<TokenStream> {
657657
};
658658
Ok(output)
659659
}
660+
661+
#[cfg(test)]
662+
mod tests {
663+
use super::*;
664+
665+
#[test]
666+
fn option_none_default_keeps_rust_value_and_metadata() {
667+
let types: [Type; 2] = [
668+
parse_quote!(Option<PyObjectRef>),
669+
parse_quote!(Option<PyStrRef>),
670+
];
671+
for ty in types {
672+
let field: Field = parse_quote! {
673+
#[pyarg(any, default = None)]
674+
value: #ty
675+
};
676+
let tokens = generate_field((0, &field)).unwrap().to_string();
677+
assert!(tokens.contains(&quote!(unwrap_or_else(|| None)).to_string()));
678+
assert!(!tokens.contains("vm . ctx . none"));
679+
let attr = ArgAttribute::try_from(&field).unwrap();
680+
let repr = repr_path();
681+
assert_eq!(
682+
signature_default(&field, &attr).unwrap().to_string(),
683+
quote!(Some(#repr::None)).to_string()
684+
);
685+
}
686+
}
687+
688+
#[test]
689+
fn none_default_keeps_wrapped_argument_paths() {
690+
let types: [Type; 3] = [
691+
parse_quote!(Option<PyObjectRef>),
692+
parse_quote!(OptionalArg<PyObjectRef>),
693+
parse_quote!(OptionalOption<PyObjectRef>),
694+
];
695+
for ty in types {
696+
let field: Field = parse_quote! {
697+
#[pyarg(any, default = None)]
698+
value: #ty
699+
};
700+
let tokens = generate_field((0, &field)).unwrap().to_string();
701+
assert!(!tokens.contains("vm . ctx . none"));
702+
assert!(tokens.contains(&quote!(unwrap_or_else(|| None)).to_string()));
703+
}
704+
}
705+
706+
#[test]
707+
fn none_is_not_a_python_object_literal() {
708+
for expr in [parse_quote!(None), parse_quote!((None))] {
709+
assert!(literal_object_expr(&expr).is_none());
710+
}
711+
for expr in [
712+
parse_quote!("text"),
713+
parse_quote!(b"bytes"),
714+
parse_quote!(true),
715+
] {
716+
assert_eq!(
717+
literal_object_expr(&expr).unwrap().to_string(),
718+
quote!(#expr).to_string()
719+
);
720+
}
721+
let field: Field = parse_quote! {
722+
#[pyarg(any, default = "text")]
723+
value: PyStrRef
724+
};
725+
let tokens = generate_field((0, &field)).unwrap().to_string();
726+
assert!(tokens.contains("< PyStrRef as :: rustpython_vm :: convert :: TryFromObject >"));
727+
assert!(!tokens.contains("vm . ctx . none"));
728+
}
729+
}
Collapse file

‎crates/derive/src/lib.rs‎

Copy file name to clipboardExpand all lines: crates/derive/src/lib.rs
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ use syn::punctuated::Punctuated;
2626
/// `OptionalArg<T>` is converted only when the argument is missing:
2727
/// `<FieldTy as TryFromObject>::try_from_object(vm, ToPyObject::to_pyobject(LIT, vm))?`.
2828
/// A byte-string literal becomes a Python `bytes` object.
29+
/// `default = None` on `Option<T>`, including `Option<PyObjectRef>`, stores
30+
/// Rust `None` and displays `None` in the signature without `py_default`.
31+
/// It does not construct Python's None object for an unwrapped field or
32+
/// mean `OptionalArg::Missing`.
2933
/// - `default = ::NAME`: `NAME` is one identifier. The signature copies that
3034
/// name, and the missing argument stores `Into::into(NAME)` (the leading
3135
/// `::` is not Rust syntax for a local constant). A longer `::` path is a

0 commit comments

Comments
0 (0)
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.