Skip to content

Commit b096651

Browse files
committed
Merge branch 'main' into modulelocals
* main: pythongh-104799: PEP 695 backward compatibility for ast.unparse (python#105846) pythongh-105834: Add tests for calling `issubclass()` between two protocols (python#105835) CI: Remove docs build from Azure Pipelines (python#105823) pythongh-105844: Consistently use 'minor version' for X.Y versions (python#105851) Fix inaccuracies in "Assorted Topics" section of "Defining Extension Types" tutorial (python#104969) pythongh-105433: Add `pickle` tests for PEP695 (python#105443) bpo-44530: Document the change in MAKE_FUNCTION behavior (python#93189) pythonGH-103124: Multiline statement support for pdb (pythonGH-103125) pythonGH-105588: Add missing error checks to some obj2ast_* converters (pythonGH-105589)
2 parents 166aca9 + 957a974 commit b096651

21 files changed

+391
-106
lines changed

.azure-pipelines/ci.yml

-14
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,6 @@ jobs:
1414
- template: ./prebuild-checks.yml
1515

1616

17-
- job: Docs_PR
18-
displayName: Docs PR
19-
dependsOn: Prebuild
20-
condition: and(succeeded(), eq(dependencies.Prebuild.outputs['docs.run'], 'true'))
21-
22-
pool:
23-
vmImage: ubuntu-22.04
24-
25-
steps:
26-
- template: ./docs-steps.yml
27-
parameters:
28-
upload: true
29-
30-
3117
- job: macOS_CI_Tests
3218
displayName: macOS CI Tests
3319
dependsOn: Prebuild

.azure-pipelines/docs-steps.yml

-47
This file was deleted.

.azure-pipelines/pr.yml

-12
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,6 @@ jobs:
1414
- template: ./prebuild-checks.yml
1515

1616

17-
- job: Docs_PR
18-
displayName: Docs PR
19-
dependsOn: Prebuild
20-
condition: and(succeeded(), eq(dependencies.Prebuild.outputs['docs.run'], 'true'))
21-
22-
pool:
23-
vmImage: ubuntu-22.04
24-
25-
steps:
26-
- template: ./docs-steps.yml
27-
28-
2917
- job: macOS_PR_Tests
3018
displayName: macOS PR Tests
3119
dependsOn: Prebuild

.azure-pipelines/prebuild-checks.yml

-12
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,6 @@ steps:
1111
displayName: Fetch comparison tree
1212
condition: and(succeeded(), variables['System.PullRequest.TargetBranch'])
1313

14-
- script: |
15-
if ! git diff --name-only $(diffTarget) | grep -qE '(\.rst$|^Doc|^Misc)'
16-
then
17-
echo "No docs were updated: docs.run=false"
18-
echo "##vso[task.setvariable variable=run;isOutput=true]false"
19-
else
20-
echo "Docs were updated: docs.run=true"
21-
echo "##vso[task.setvariable variable=run;isOutput=true]true"
22-
fi
23-
displayName: Detect documentation changes
24-
name: docs
25-
2614
- script: |
2715
if ! git diff --name-only $(diffTarget) | grep -qvE '(\.rst$|^Doc|^Misc)'
2816
then

Doc/extending/newtypes.rst

+5-5
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ representation of the instance for which it is called. Here is a simple
168168
example::
169169

170170
static PyObject *
171-
newdatatype_repr(newdatatypeobject * obj)
171+
newdatatype_repr(newdatatypeobject *obj)
172172
{
173173
return PyUnicode_FromFormat("Repr-ified_newdatatype{{size:%d}}",
174174
obj->obj_UnderlyingDatatypePtr->size);
@@ -188,7 +188,7 @@ used instead.
188188
Here is a simple example::
189189

190190
static PyObject *
191-
newdatatype_str(newdatatypeobject * obj)
191+
newdatatype_str(newdatatypeobject *obj)
192192
{
193193
return PyUnicode_FromFormat("Stringified_newdatatype{{size:%d}}",
194194
obj->obj_UnderlyingDatatypePtr->size);
@@ -338,7 +338,7 @@ Here is an example::
338338

339339
PyErr_Format(PyExc_AttributeError,
340340
"'%.100s' object has no attribute '%.400s'",
341-
tp->tp_name, name);
341+
Py_TYPE(obj)->tp_name, name);
342342
return NULL;
343343
}
344344

@@ -379,7 +379,7 @@ Here is a sample implementation, for a datatype that is considered equal if the
379379
size of an internal pointer is equal::
380380

381381
static PyObject *
382-
newdatatype_richcmp(PyObject *obj1, PyObject *obj2, int op)
382+
newdatatype_richcmp(newdatatypeobject *obj1, newdatatypeobject *obj2, int op)
383383
{
384384
PyObject *result;
385385
int c, size1, size2;
@@ -478,7 +478,7 @@ This function takes three arguments:
478478
Here is a toy ``tp_call`` implementation::
479479

480480
static PyObject *
481-
newdatatype_call(newdatatypeobject *self, PyObject *args, PyObject *kwds)
481+
newdatatype_call(newdatatypeobject *obj, PyObject *args, PyObject *kwds)
482482
{
483483
PyObject *result;
484484
const char *arg1;

Doc/faq/general.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ Python versions are numbered "A.B.C" or "A.B":
135135

136136
See :pep:`6` for more information about bugfix releases.
137137

138-
Not all releases are bugfix releases. In the run-up to a new major release, a
138+
Not all releases are bugfix releases. In the run-up to a new minor release, a
139139
series of development releases are made, denoted as alpha, beta, or release
140140
candidate. Alphas are early releases in which interfaces aren't yet finalized;
141141
it's not unexpected to see an interface change between two alpha releases.
@@ -297,7 +297,7 @@ How stable is Python?
297297

298298
Very stable. New, stable releases have been coming out roughly every 6 to 18
299299
months since 1991, and this seems likely to continue. As of version 3.9,
300-
Python will have a major new release every 12 months (:pep:`602`).
300+
Python will have a minor new release every 12 months (:pep:`602`).
301301

302302
The developers issue "bugfix" releases of older versions, so the stability of
303303
existing releases gradually improves. Bugfix releases, indicated by a third

Doc/install/index.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,7 @@ is supplied to suppress this behaviour. So you could simply edit
696696
import sys
697697
sys.path.append('/www/python/')
698698
699-
However, if you reinstall the same major version of Python (perhaps when
699+
However, if you reinstall the same minor version of Python (perhaps when
700700
upgrading from 2.2 to 2.2.2, for example) :file:`site.py` will be overwritten by
701701
the stock version. You'd have to remember that it was modified and save a copy
702702
before doing the installation.

Doc/library/dis.rst

+5-2
Original file line numberDiff line numberDiff line change
@@ -1431,12 +1431,15 @@ iterations of the loop.
14311431
* ``0x02`` a dictionary of keyword-only parameters' default values
14321432
* ``0x04`` a tuple of strings containing parameters' annotations
14331433
* ``0x08`` a tuple containing cells for free variables, making a closure
1434-
* the code associated with the function (at ``STACK[-2]``)
1435-
* the :term:`qualified name` of the function (at ``STACK[-1]``)
1434+
* the code associated with the function (at ``STACK[-1]``)
14361435

14371436
.. versionchanged:: 3.10
14381437
Flag value ``0x04`` is a tuple of strings instead of dictionary
14391438

1439+
.. versionchanged:: 3.11
1440+
Qualified name at ``STACK[-1]`` was removed.
1441+
1442+
14401443
.. opcode:: BUILD_SLICE (argc)
14411444

14421445
.. index:: pair: built-in function; slice

Lib/ast.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -1051,7 +1051,8 @@ def visit_ClassDef(self, node):
10511051
self.fill("@")
10521052
self.traverse(deco)
10531053
self.fill("class " + node.name)
1054-
self._type_params_helper(node.type_params)
1054+
if hasattr(node, "type_params"):
1055+
self._type_params_helper(node.type_params)
10551056
with self.delimit_if("(", ")", condition = node.bases or node.keywords):
10561057
comma = False
10571058
for e in node.bases:
@@ -1083,7 +1084,8 @@ def _function_helper(self, node, fill_suffix):
10831084
self.traverse(deco)
10841085
def_str = fill_suffix + " " + node.name
10851086
self.fill(def_str)
1086-
self._type_params_helper(node.type_params)
1087+
if hasattr(node, "type_params"):
1088+
self._type_params_helper(node.type_params)
10871089
with self.delimit("(", ")"):
10881090
self.traverse(node.args)
10891091
if node.returns:

Lib/pdb.py

+25-1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
import dis
7777
import code
7878
import glob
79+
import codeop
7980
import pprint
8081
import signal
8182
import inspect
@@ -444,7 +445,30 @@ def default(self, line):
444445
locals = self.curframe_locals
445446
globals = self.curframe.f_globals
446447
try:
447-
code = compile(line + '\n', '<stdin>', 'single')
448+
if (code := codeop.compile_command(line + '\n', '<stdin>', 'single')) is None:
449+
# Multi-line mode
450+
buffer = line
451+
continue_prompt = "... "
452+
while (code := codeop.compile_command(buffer, '<stdin>', 'single')) is None:
453+
if self.use_rawinput:
454+
try:
455+
line = input(continue_prompt)
456+
except (EOFError, KeyboardInterrupt):
457+
self.lastcmd = ""
458+
print('\n')
459+
return
460+
else:
461+
self.stdout.write(continue_prompt)
462+
self.stdout.flush()
463+
line = self.stdin.readline()
464+
if not len(line):
465+
self.lastcmd = ""
466+
self.stdout.write('\n')
467+
self.stdout.flush()
468+
return
469+
else:
470+
line = line.rstrip('\r\n')
471+
buffer += '\n' + line
448472
save_stdout = sys.stdout
449473
save_stdin = sys.stdin
450474
save_displayhook = sys.displayhook

Lib/test/test_ast.py

+27
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import dis
44
import enum
55
import os
6+
import re
67
import sys
78
import textwrap
89
import types
@@ -1110,6 +1111,32 @@ def test_null_bytes(self):
11101111
msg="source code string cannot contain null bytes"):
11111112
ast.parse("a\0b")
11121113

1114+
def assert_none_check(self, node: type[ast.AST], attr: str, source: str) -> None:
1115+
with self.subTest(f"{node.__name__}.{attr}"):
1116+
tree = ast.parse(source)
1117+
found = 0
1118+
for child in ast.walk(tree):
1119+
if isinstance(child, node):
1120+
setattr(child, attr, None)
1121+
found += 1
1122+
self.assertEqual(found, 1)
1123+
e = re.escape(f"field '{attr}' is required for {node.__name__}")
1124+
with self.assertRaisesRegex(ValueError, f"^{e}$"):
1125+
compile(tree, "<test>", "exec")
1126+
1127+
def test_none_checks(self) -> None:
1128+
tests = [
1129+
(ast.alias, "name", "import spam as SPAM"),
1130+
(ast.arg, "arg", "def spam(SPAM): spam"),
1131+
(ast.comprehension, "target", "[spam for SPAM in spam]"),
1132+
(ast.comprehension, "iter", "[spam for spam in SPAM]"),
1133+
(ast.keyword, "value", "spam(**SPAM)"),
1134+
(ast.match_case, "pattern", "match spam:\n case SPAM: spam"),
1135+
(ast.withitem, "context_expr", "with SPAM: spam"),
1136+
]
1137+
for node, attr, source in tests:
1138+
self.assert_none_check(node, attr, source)
1139+
11131140
class ASTHelpers_Test(unittest.TestCase):
11141141
maxDiff = None
11151142

Lib/test/test_pdb.py

+30-3
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ def test_pdb_breakpoints_preserved_across_interactive_sessions():
389389
1 breakpoint keep yes at ...test_pdb.py:...
390390
2 breakpoint keep yes at ...test_pdb.py:...
391391
(Pdb) break pdb.find_function
392-
Breakpoint 3 at ...pdb.py:97
392+
Breakpoint 3 at ...pdb.py:...
393393
(Pdb) break
394394
Num Type Disp Enb Where
395395
1 breakpoint keep yes at ...test_pdb.py:...
@@ -1589,6 +1589,32 @@ def test_pdb_next_command_subiterator():
15891589
(Pdb) continue
15901590
"""
15911591

1592+
def test_pdb_multiline_statement():
1593+
"""Test for multiline statement
1594+
1595+
>>> def test_function():
1596+
... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
1597+
... pass
1598+
1599+
>>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE
1600+
... 'def f(x):',
1601+
... ' return x * 2',
1602+
... '',
1603+
... 'f(2)',
1604+
... 'c'
1605+
... ]):
1606+
... test_function()
1607+
> <doctest test.test_pdb.test_pdb_multiline_statement[0]>(3)test_function()
1608+
-> pass
1609+
(Pdb) def f(x):
1610+
... return x * 2
1611+
...
1612+
(Pdb) f(2)
1613+
4
1614+
(Pdb) c
1615+
"""
1616+
1617+
15921618
def test_pdb_issue_20766():
15931619
"""Test for reference leaks when the SIGINT handler is set.
15941620
@@ -2362,7 +2388,7 @@ def test_relative_imports_on_plain_module(self):
23622388

23632389
def test_errors_in_command(self):
23642390
commands = "\n".join([
2365-
'print(',
2391+
'print(]',
23662392
'debug print(',
23672393
'debug doesnotexist',
23682394
'c',
@@ -2371,7 +2397,8 @@ def test_errors_in_command(self):
23712397

23722398
self.assertEqual(stdout.splitlines()[1:], [
23732399
'-> pass',
2374-
'(Pdb) *** SyntaxError: \'(\' was never closed',
2400+
"(Pdb) *** SyntaxError: closing parenthesis ']' does not match opening "
2401+
"parenthesis '('",
23752402

23762403
'(Pdb) ENTERING RECURSIVE DEBUGGER',
23772404
'*** SyntaxError: \'(\' was never closed',

0 commit comments

Comments
 (0)