10000 Pull in main · python/cpython@daea15e · GitHub
[go: up one dir, main page]

Skip to content

Commit daea15e

Browse files
Pull in main
2 parents 61bef45 + aab6f71 commit daea15e

File tree

7 files changed

+114
-24
lines changed

7 files changed

+114
-24
lines changed

Doc/library/functions.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1752,7 +1752,7 @@ are always available. They are listed here in alphabetical order.
17521752
The *start* parameter can be specified as a keyword argument.
17531753

17541754
.. versionchanged:: 3.12 Summation of floats switched to an algorithm
1755-
that gives higher accuracy on most builds.
1755+
that gives higher accuracy and better commutativity on most builds.
17561756

17571757

17581758
.. class:: super()

Doc/whatsnew/3.12.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -504,8 +504,8 @@ Other Language Changes
504504
* :class:`slice` objects are now hashable, allowing them to be used as dict keys and
505505
set items. (Contributed by Will Bradshaw, Furkan Onder, and Raymond Hettinger in :gh:`101264`.)
506506

507-
* :func:`sum` now uses Neumaier summation to improve accuracy when summing
508-
floats or mixed ints and floats.
507+
* :func:`sum` now uses Neumaier summation to improve accuracy and commutativity
508+
when summing floats or mixed ints and floats.
509509
(Contributed by Raymond Hettinger in :gh:`100425`.)
510510

511511
* Exceptions raised in a typeobject's ``__set_name__`` method are no longer

Lib/statistics.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,14 @@ def _mean_stdev(data):
10041004
# Handle Nans and Infs gracefully
10051005
return float(xbar), float(xbar) / float(ss)
10061006

1007+
def _sqrtprod(x: float, y: float) -> float:
1008+
"Return sqrt(x * y) computed with high accuracy."
1009+
# Square root differential correction:
1010+
# https://www.wolframalpha.com/input/?i=Maclaurin+series+sqrt%28h**2+%2B+x%29+at+x%3D0
1011+
h = sqrt(x * y)
1012+
x = sumprod((x, h), (y, -h))
1013+
return h + x / (2.0 * h)
1014+
10071015

10081016
# === Statistics for relations between two inputs ===
10091017

@@ -1083,7 +1091,7 @@ def correlation(x, y, /, *, method='linear'):
10831091
sxx = sumprod(x, x)
10841092
syy = sumprod(y, y)
10851093
try:
1086-
return sxy / sqrt(sxx * syy)
1094+
return sxy / _sqrtprod(sxx, syy)
10871095
except ZeroDivisionError:
10881096
raise StatisticsError('at least one of the inputs is constant')
10891097

Lib/test/test_clinic.py

Lines changed: 94 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ def _expect_failure(tc, parser, code, errmsg, *, filename=None, lineno=None):
4545
tc.assertEqual(cm.exception.filename, filename)
4646
if lineno is not None:
4747
tc.assertEqual(cm.exception.lineno, lineno)
48+
return cm.exception
4849

4950

5051
class ClinicWholeFileTest(TestCase):
@@ -222,6 +223,15 @@ def test_directive_output_print(self):
222223
last_line.startswith("/*[clinic end generated code: output=")
223224
)
224225

226+
def test_directive_wrong_arg_number(self):
227+
raw = dedent("""
228+
/*[clinic input]
229+
preserve foo bar baz eggs spam ham mushrooms
230+
[clinic start generated code]*/
231+
""")
232+
err = "takes 1 positional argument but 8 were given"
233+
self.expect_failure(raw, err)
234+
225235
def test_unknown_destination_command(self):
226236
raw = """
227237
/*[clinic input]
@@ -600,6 +610,31 @@ def test_directive_output_invalid_command(self):
600610
self.expect_failure(block, err, lineno=2)
601611

602612

613+
class ParseFileUnitTest(TestCase):
614+
def expect_parsing_failure(
615+
self, *, filename, expected_error, verify=True, output=None
616+
):
617+
errmsg = re.escape(dedent(expected_error).strip())
618+
with self.assertRaisesRegex(clinic.ClinicError, errmsg):
619+
clinic.parse_file(filename)
620+
621+
def test_parse_file_no_extension(self) -> None:
622+
self.expect_parsing_failure(
623+
filename="foo",
624+
expected_error="Can't extract file type for file 'foo'"
625+
)
626+
627+
def test_parse_file_strange_extension(self) -> None:
628+
filenames_to_errors = {
629+
"foo.rs": "Can't identify file type for file 'foo.rs'",
630+
"foo.hs": "Can't identify file type for file 'foo.hs'",
631+
"foo.js": "Can't identify file type for file 'foo.js'",
632+
}
633+
for filename, errmsg in filenames_to_errors.items():
634+
with self.subTest(filename=filename):
635+
self.expect_parsing_failure(filename=filename, expected_error=errmsg)
636+
637+
603638
class ClinicGroupPermuterTest(TestCase):
604639
def _test(self, l, m, r, output):
605640
computed = clinic.permute_optional_groups(l, m, r)
@@ -794,8 +829,8 @@ def parse_function(self, text, signatures_in_block=2, function_index=1):
794829
return s[function_index]
795830

796831
def expect_failure(self, block, err, *, filename=None, lineno=None):
797-
_expect_failure(self, self.parse_function, block, err,
798-
filename=filename, lineno=lineno)
832+
return _expect_failure(self, self.parse_function, block, err,
833+
filename=filename, lineno=lineno)
799834

800835
def checkDocstring(self, fn, expected):
801836
self.assertTrue(hasattr(fn, "docstring"))
@@ -877,6 +912,41 @@ def test_param_default_expr_named_constant(self):
877912
"""
878913
self.expect_failure(block, err, lineno=2)
879914

915+
def test_param_with_bizarre_default_fails_correctly(self):
916+
template = """
917+
module os
918+
os.access
919+
follow_symlinks: int = {default}
920+
"""
921+
err = "Unsupported expression as default value"
922+
for bad_default_value in (
923+
"{1, 2, 3}",
924+
"3 if bool() else 4",
925+
"[x for x in range(42)]"
926+
):
927+
with self.subTest(bad_default=bad_default_value):
928+
block = template.format(default=bad_default_value)
929+
self.expect_failure(block, err, lineno=2)
930+
931+
def test_unspecified_not_allowed_as_default_value(self):
932+
block = """
933+
module os
934+
os.access
935+
follow_symlinks: int(c_default='MAXSIZE') = unspecified
936+
"""
937+
err = "'unspecified' is not a legal default value!"
938+
exc = self.expect_failure(block, err, lineno=2)
939+
self.assertNotIn('Malformed expression given as default value', str(exc))
940+
941+
def test_malformed_expression_as_default_value(self):
942+
block = """
943+
module os
944+
os.access
945+
follow_symlinks: int(c_default='MAXSIZE') = 1/0
946+
"""
947+
err = "Malformed expression given as default value"
948+
self.expect_failure(block, err, lineno=2)
949+
880950
def test_param_default_expr_binop(self):
881951
err = (
882952
"When you specify an expression ('a + b') as your default value, "
@@ -1041,6 +1111,28 @@ def test_c_name(self):
10411111
""")
10421112
self.assertEqual("os_stat_fn", function.c_basename)
10431113

1114+
def test_base_invalid_syntax(self):
1115+
block = """
1116+
module os
1117+
os.stat
1118+
invalid syntax: int = 42
1119+
"""
1120+
err = dedent(r"""
1121+
Function 'stat' has an invalid parameter declaration:
1122+
\s+'invalid syntax: int = 42'
1123+
""").strip()
1124+
with self.assertRaisesRegex(clinic.ClinicError, err):
1125+
self.parse_function(block)
1126+
1127+
def test_param_default_invalid_syntax(self):
1128+
block = """
1129+
module os
1130+
os.stat
1131+
x: int = invalid syntax
1132+
"""
1133+
err = r"Syntax error: 'x = invalid syntax\n'"
1134+
self.expect_failure(block, err, lineno=2)
1135+
10441136
def test_cloning_nonexistent_function_correctly_fails(self):
10451137
block = """
10461138
cloned = fooooooooooooooooo
@@ -1414,18 +1506,6 @@ def test_parameters_required_after_star(self):
14141506
with self.subTest(block=block):
14151507
self.expect_failure(block, err)
14161508

1417-
def test_parameters_required_after_depr_star(self):
1418-
dataset = (
1419-
"module foo\nfoo.bar\n * [from 3.14]",
1420-
"module foo\nfoo.bar\n * [from 3.14]\nDocstring here.",
1421-
"module foo\nfoo.bar\n this: int\n * [from 3.14]",
1422-
"module foo\nfoo.bar\n this: int\n * [from 3.14]\nDocstring.",
1423-
)
1424-
err = "Function 'foo.bar' specifies '* [from 3.14]' without any parameters afterwards."
1425-
for block in dataset:
1426-
with self.subTest(block=block):
1427-
self.expect_failure(block, err)
1428-
14291509
def test_depr_star_invalid_format_1(self):
14301510
block = """
14311511
module foo

Lib/test/test_interpreters.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,6 @@ def test_bytes_for_script(self):
464464
# test_xxsubinterpreters covers the remaining Interpreter.run() behavior.
465465

466466

467-
@unittest.skip('these are crashing, likely just due just to _xxsubinterpreters (see gh-105699)')
468467
class StressTests(TestBase):
469468

470469
# In these tests we generally want a lot of interpreters,

PCbuild/readme.txt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,11 @@ against a profiling library and contain extra debug information. The
251251
PGUpdate configuration takes the profiling data and generates optimized
252252
binaries.
253253

254-
The build_pgo.bat script automates the creation of optimized binaries.
255-
It creates the PGI files, runs the unit test suite or PyBench with the
256-
PGI python, and finally creates the optimized files.
254+
The build.bat script has an argument `--pgo` that automate the creation
255+
of optimized binaries.
256+
It creates the PGI files, runs the unit test suite with the PGI python,
257+
and finally creates the optimized files.
258+
You can customize the job for profiling with `--pgo-job <job>` option.
257259

258260
See
259261
https://docs.microsoft.com/en-us/cpp/build/profile-guided-optimizations

Tools/clinic/clinic.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5207,13 +5207,14 @@ def bad_node(self, node: ast.AST) -> None:
52075207
# but at least make an attempt at ensuring it's a valid expression.
52085208
try:
52095209
value = eval(default)
5210-
if value is unspecified:
5211-
fail("'unspecified' is not a legal default value!")
52125210
except NameError:
52135211
pass # probably a named constant
52145212
except Exception as e:
52155213
fail("Malformed expression given as default value "
52165214
f"{default!r} caused {e!r}")
5215+
else:
5216+
if value is unspecified:
5217+
fail("'unspecified' is not a legal default value!")
52175218
if bad:
52185219
fail(f"Unsupported expression as default value: {default!r}")
52195220

0 commit comments

Comments
 (0)
0