Skip to content

Commit 1a137bc

Browse files
committed
Merge branch 'main' of https://github.com/python/cpython
2 parents ee49644 + 50b52cb commit 1a137bc

File tree

6 files changed

+61
-14
lines changed

6 files changed

+61
-14
lines changed

Lib/curses/__init__.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,8 @@ def initscr():
3030
fd=_sys.__stdout__.fileno())
3131
stdscr = _curses.initscr()
3232
for key, value in _curses.__dict__.items():
33-
if key[0:4] == 'ACS_' or key in ('LINES', 'COLS'):
33+
if key.startswith('ACS_') or key in ('LINES', 'COLS'):
3434
setattr(curses, key, value)
35-
3635
return stdscr
3736

3837
# This is a similar wrapper for start_color(), which adds the COLORS and
@@ -41,12 +40,9 @@ def initscr():
4140

4241
def start_color():
4342
import _curses, curses
44-
retval = _curses.start_color()
45-
if hasattr(_curses, 'COLORS'):
46-
curses.COLORS = _curses.COLORS
47-
if hasattr(_curses, 'COLOR_PAIRS'):
48-
curses.COLOR_PAIRS = _curses.COLOR_PAIRS
49-
return retval
43+
_curses.start_color()
44+
curses.COLORS = _curses.COLORS
45+
curses.COLOR_PAIRS = _curses.COLOR_PAIRS
5046

5147
# Import Python has_key() implementation if _curses doesn't contain has_key()
5248

@@ -85,10 +81,11 @@ def wrapper(func, /, *args, **kwds):
8581
# Start color, too. Harmless if the terminal doesn't have
8682
# color; user can test with has_color() later on. The try/catch
8783
# works around a minor bit of over-conscientiousness in the curses
88-
# module -- the error return from C start_color() is ignorable.
84+
# module -- the error return from C start_color() is ignorable,
85+
# unless they are raised by the interpreter due to other issues.
8986
try:
9087
start_color()
91-
except:
88+
except _curses.error:
9289
pass
9390

9491
return func(stdscr, *args, **kwds)

Lib/test/test_ast/test_ast.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,17 @@ def test_constant_as_name(self):
821821
with self.assertRaisesRegex(ValueError, f"identifier field can't represent '{constant}' constant"):
822822
compile(expr, "<test>", "eval")
823823

824+
def test_constant_as_unicode_name(self):
825+
constants = [
826+
("True", b"Tru\xe1\xb5\x89"),
827+
("False", b"Fal\xc5\xbfe"),
828+
("None", b"N\xc2\xbane"),
829+
]
830+
for constant in constants:
831+
with self.assertRaisesRegex(ValueError,
832+
f"identifier field can't represent '{constant[0]}' constant"):
833+
ast.parse(constant[1], mode="eval")
834+
824835
def test_precedence_enum(self):
825836
class _Precedence(enum.IntEnum):
826837
"""Precedence table that originated from python grammar."""
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Raise :exc:`ValueError` when constants ``True``, ``False`` or ``None`` are
2+
used as an identifier after NFKC normalization.

Parser/pegen.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,21 @@ _PyPegen_new_identifier(Parser *p, const char *n)
549549
}
550550
id = id2;
551551
}
552+
static const char * const forbidden[] = {
553+
"None",
554+
"True",
555+
"False",
556+
NULL
557+
};
558+
for (int i = 0; forbidden[i] != NULL; i++) {
559+
if (_PyUnicode_EqualToASCIIString(id, forbidden[i])) {
560+
PyErr_Format(PyExc_ValueError,
561+
"identifier field can't represent '%s' constant",
562+
forbidden[i]);
563+
Py_DECREF(id);
564+
goto error;
565+
}
566+
}
552567
PyInterpreterState *interp = _PyInterpreterState_GET();
553568
_PyUnicode_InternImmortal(interp, &id);
554569
if (_PyArena_AddPyObject(p->arena, id) < 0)

Tools/build/mypy.ini

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
[mypy]
22
files =
33
Tools/build/compute-changes.py,
4-
Tools/build/generate_sbom.py
4+
Tools/build/generate_sbom.py,
5+
Tools/build/update_file.py
6+
57
pretty = True
68

79
# Make sure Python can still be built
@@ -10,6 +12,8 @@ python_version = 3.10
1012

1113
# ...And be strict:
1214
strict = True
15+
strict_bytes = True
16+
local_partial_types = True
1317
extra_checks = True
1418
enable_error_code = ignore-without-code,redundant-expr,truthy-bool,possibly-undefined
1519
warn_unreachable = True

Tools/build/update_file.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,27 @@
66
actually change the in-tree generated code.
77
"""
88

9+
from __future__ import annotations
10+
911
import contextlib
1012
import os
1113
import os.path
1214
import sys
1315

16+
TYPE_CHECKING = False
17+
if TYPE_CHECKING:
18+
import typing
19+
from collections.abc import Iterator
20+
from io import TextIOWrapper
21+
22+
_Outcome: typing.TypeAlias = typing.Literal['created', 'updated', 'same']
23+
1424

1525
@contextlib.contextmanager
16-
def updating_file_with_tmpfile(filename, tmpfile=None):
26+
def updating_file_with_tmpfile(
27+
filename: str,
28+
tmpfile: str | None = None,
29+
) -> Iterator[tuple[TextIOWrapper, TextIOWrapper]]:
1730
"""A context manager for updating a file via a temp file.
1831
1932
The context manager provides two open files: the source file open
@@ -46,13 +59,18 @@ def updating_file_with_tmpfile(filename, tmpfile=None):
4659
update_file_with_tmpfile(filename, tmpfile)
4760

4861

49-
def update_file_with_tmpfile(filename, tmpfile, *, create=False):
62+
def update_file_with_tmpfile(
63+
filename: str,
64+
tmpfile: str,
65+
*,
66+
create: bool = False,
67+
) -> _Outcome:
5068
try:
5169
targetfile = open(filename, 'rb')
5270
except FileNotFoundError:
5371
if not create:
5472
raise # re-raise
55-
outcome = 'created'
73+
outcome: _Outcome = 'created'
5674
os.replace(tmpfile, filename)
5775
else:
5876
with targetfile:

0 commit comments

Comments
 (0)