Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-45292: [PEP-654] add except* #29581

Merged
merged 50 commits into from
Dec 14, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
b0ca0b7
bpo-45292: [PEP-654] add except*
iritkatriel Nov 11, 2021
cad9126
fold invalid_except_star_stmt into invalid_except_stmt. Add custom me…
iritkatriel Nov 17, 2021
798aaa7
Erlend's first review
iritkatriel Nov 17, 2021
f95272c
fix grammar rule for mixed except/except*
iritkatriel Nov 18, 2021
ca44878
fix doctest failure
iritkatriel Nov 18, 2021
adc834d
remove duplication in except* handling
iritkatriel Nov 19, 2021
e3fa2f7
fix bug - move POP_BLOCK to the end in case of except*
iritkatriel Nov 19, 2021
1908fd8
Merge remote-tracking branch 'upstream/main' into bpo-45292-except_star
iritkatriel Nov 21, 2021
5846329
Merge remote-tracking branch 'upstream/main' into bpo-45292-except_star
iritkatriel Nov 21, 2021
f9a626c
Use Py_NewRef(_PyLong_GetZero());
iritkatriel Nov 21, 2021
fdc948b
Split AST node Try -> Try/TryStar. Separate try-except and try-except…
iritkatriel Nov 22, 2021
488f9fa
Revert doctest changes (not needed with TryStar)
iritkatriel Nov 22, 2021
4eff693
a pesky little decref
iritkatriel Nov 22, 2021
211d6da
📜🤖 Added by blurb_it.
blurb-it[bot] Nov 22, 2021
03dbf43
update unparse for TryStar
iritkatriel Nov 22, 2021
704bc8f
update ast doc with TryStar
iritkatriel Nov 22, 2021
ff36e5d
add try-star test in test_grammar
iritkatriel Nov 22, 2021
73ee294
add test for invalid exception matcher (old except)
iritkatriel Nov 22, 2021
51e8178
break/ continue/return in except* block is SyntaxError
iritkatriel Nov 22, 2021
50a2126
add stack stability tests for except*
iritkatriel Nov 22, 2021
1d9969d
Merge remote-tracking branch 'upstream/main' into bpo-45292-except_star
iritkatriel Nov 22, 2021
4a7bf9f
remove commented out debug prints
iritkatriel Nov 23, 2021
3ad5d41
add trace tests for except*
iritkatriel Nov 24, 2021
2813363
remove obsolete comment
iritkatriel Nov 24, 2021
7e54805
formatting of comment
iritkatriel Nov 25, 2021
5736f15
save step before try
iritkatriel Nov 25, 2021
82a4db3
add diagram of stack contents durign except*
iritkatriel Nov 25, 2021
a461e7d
one more save step before try
iritkatriel Nov 25, 2021
be609b3
fix diagram
iritkatriel Nov 25, 2021
706e54b
fix diagram some more
iritkatriel Nov 25, 2021
7f49575
treat JUMP_IF_NOT_EG_MATCH like *_EXC_MATCH in mark_stacks
iritkatriel Nov 27, 2021
ae729f3
whatnew in 3.11
iritkatriel Nov 27, 2021
38e3b50
Merge branch 'main' into bpo-45292-except_star
ambv Nov 30, 2021
ee53c8d
Merge remote-tracking branch 'upstream/main' into bpo-45292-except_star
iritkatriel Dec 5, 2021
9c18862
Merge remote-tracking branch 'upstream/main' into bpo-45292-except_star
iritkatriel Dec 7, 2021
7428b15
Merge remote-tracking branch 'upstream/main' into bpo-45292-except_star
iritkatriel Dec 8, 2021
bbe44fb
fix typos in dis doc entry
iritkatriel Dec 8, 2021
22bf207
"three items" --> "3items"
iritkatriel Dec 8, 2021
66d830a
add spaces
iritkatriel Dec 8, 2021
f2b74a5
Merge remote-tracking branch 'upstream/main' into bpo-45292-except_star
iritkatriel Dec 10, 2021
035fe5c
Apply first batch of suggestions from code review
iritkatriel Dec 11, 2021
5d52de3
the remaining comments from Erlend
iritkatriel Dec 11, 2021
a1591f0
sign what's new
iritkatriel Dec 11, 2021
ce36211
Merge remote-tracking branch 'upstream/main' into bpo-45292-except_star
iritkatriel Dec 11, 2021
20d9ccd
'== -1' --> '< 0' for consistency. Added a missing recursion guard.
iritkatriel Dec 12, 2021
3a642e6
Merge remote-tracking branch 'upstream/main' into bpo-45292-except_star
iritkatriel Dec 12, 2021
13e0d0f
Merge branch 'main' into bpo-45292-except_star
iritkatriel Dec 13, 2021
078f050
whitespace
iritkatriel Dec 14, 2021
a91b219
Merge branch 'bpo-45292-except_star' of https://github.com/iritkatrie…
iritkatriel Dec 14, 2021
564b8a0
Merge remote-tracking branch 'upstream/main' into bpo-45292-except_star
iritkatriel Dec 14, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions Doc/library/dis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -870,8 +870,10 @@ All of the following opcodes use their arguments.

.. versionadded:: 3.1


.. opcode:: JUMP_IF_NOT_EXC_MATCH (target)

Performs exception matching for ``except``.
Tests whether the second value on the stack is an exception matching TOS,
and jumps if it is not. Pops one value from the stack.

Expand All @@ -881,6 +883,29 @@ All of the following opcodes use their arguments.
This opcode no longer pops the active exception.


.. opcode:: JUMP_IF_NOT_EG_MATCH (target)

Performs exception matching for except*. Applies ``split(TOS)`` on
iritkatriel marked this conversation as resolved.
Show resolved Hide resolved
the exception group representing TOS1. Jumps if no match is found.

Pops one item from the stack. If a match was found, pops the 3 items representing
the exception and replaces them with the triplets for the non-matching part,
and above it the matching part.
iritkatriel marked this conversation as resolved.
Show resolved Hide resolved
iritkatriel marked this conversation as resolved.
Show resolved Hide resolved

.. versionadded:: 3.11


.. opcode:: PREP_RERAISE_STAR

Combines the raised and reraised exceptions list from TOS, into an exception
group to propagate from a try-except* block. Uses the original exception
group from TOS1 to reconstruct the structure of reraised exceptions. Pops
two items from the stack and pushes a triplet representing the exception to
reraise or three ``None`` if there isn't one.
gvanrossum marked this conversation as resolved.
Show resolved Hide resolved

.. versionadded:: 3.11


.. opcode:: JUMP_IF_TRUE_OR_POP (target)

If TOS is true, sets the bytecode counter to *target* and leaves TOS on the
Expand Down
19 changes: 17 additions & 2 deletions Grammar/python.gram
Original file line number Diff line number Diff line change
Expand Up @@ -401,8 +401,10 @@ with_item[withitem_ty]:

try_stmt[stmt_ty]:
| invalid_try_stmt
| 'try' &&':' b=block f=finally_block { _PyAST_Try(b, NULL, NULL, f, EXTRA) }
| 'try' &&':' b=block ex[asdl_excepthandler_seq*]=except_block+ el=[else_block] f=[finally_block] { _PyAST_Try(b, ex, el, f, EXTRA) }
| 'try' &&':' b=block f=finally_block { _PyAST_Try(b, NULL, NULL, f, 0, EXTRA) }
| 'try' &&':' b=block ex[asdl_excepthandler_seq*]=except_block+ el=[else_block] f=[finally_block] { _PyAST_Try(b, ex, el, f, 0, EXTRA) }
| 'try' &&':' b=block ex[asdl_excepthandler_seq*]=except_star_block+ el=[else_block] f=[finally_block] { _PyAST_Try(b, ex, el, f, 1, EXTRA) }


# Except statement
# ----------------
Expand All @@ -413,6 +415,11 @@ except_block[excepthandler_ty]:
_PyAST_ExceptHandler(e, (t) ? ((expr_ty) t)->v.Name.id : NULL, b, EXTRA) }
| 'except' ':' b=block { _PyAST_ExceptHandler(NULL, NULL, b, EXTRA) }
| invalid_except_stmt
except_star_block[excepthandler_ty]:
| invalid_except_star_stmt_indent
iritkatriel marked this conversation as resolved.
Show resolved Hide resolved
| 'except' '*' e=expression t=['as' z=NAME { z }] ':' b=block {
_PyAST_ExceptHandler(e, (t) ? ((expr_ty) t)->v.Name.id : NULL, b, EXTRA) }
| invalid_except_star_stmt
finally_block[asdl_stmt_seq*]:
| invalid_finally_stmt
| 'finally' &&':' a=block { a }
Expand Down Expand Up @@ -1192,13 +1199,21 @@ invalid_except_stmt:
RAISE_SYNTAX_ERROR_STARTING_FROM(a, "multiple exception types must be parenthesized") }
| a='except' expression ['as' NAME ] NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
| a='except' NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
invalid_except_star_stmt:
| 'except' '*' a=expression ',' expressions ['as' NAME ] ':' {
RAISE_SYNTAX_ERROR_STARTING_FROM(a, "multiple exception types must be parenthesized") }
| a='except' '*' expression ['as' NAME ] NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
| a='except' '*' (NEWLINE | ':') { RAISE_SYNTAX_ERROR("expected one or more exception types") }
invalid_finally_stmt:
| a='finally' ':' NEWLINE !INDENT {
RAISE_INDENTATION_ERROR("expected an indented block after 'finally' statement on line %d", a->lineno) }
invalid_except_stmt_indent:
| a='except' expression ['as' NAME ] ':' NEWLINE !INDENT {
RAISE_INDENTATION_ERROR("expected an indented block after 'except' statement on line %d", a->lineno) }
| a='except' ':' NEWLINE !INDENT { RAISE_SYNTAX_ERROR("expected an indented block after except statement on line %d", a->lineno) }
invalid_except_star_stmt_indent:
| a='except' '*' expression ['as' NAME ] ':' NEWLINE !INDENT {
RAISE_INDENTATION_ERROR("expected an indented block after 'except*' statement on line %d", a->lineno) }
invalid_match_stmt:
| "match" subject_expr !':' { CHECK_VERSION(void*, 10, "Pattern matching is", RAISE_SYNTAX_ERROR("expected ':'") ) }
| a="match" subject=subject_expr ':' NEWLINE !INDENT {
Expand Down
7 changes: 4 additions & 3 deletions Include/internal/pycore_ast.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Include/internal/pycore_ast_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ struct ast_state {
PyObject *right;
PyObject *simple;
PyObject *slice;
PyObject *star;
PyObject *step;
PyObject *stmt_type;
PyObject *subject;
Expand Down
8 changes: 8 additions & 0 deletions Include/internal/pycore_pyerrors.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@ PyAPI_FUNC(PyObject *) _PyErr_FormatFromCauseTstate(
const char *format,
...);

PyAPI_FUNC(PyObject *) _PyExc_CreateExceptionGroup(
const char *msg,
PyObject *excs);

PyAPI_FUNC(PyObject *) _PyExc_ExceptionGroupProjection(
PyObject *left,
PyObject *right);

PyAPI_FUNC(int) _PyErr_CheckSignalsTstate(PyThreadState *tstate);

PyAPI_FUNC(void) _Py_DumpExtensionModules(int fd, PyInterpreterState *interp);
Expand Down
4 changes: 3 additions & 1 deletion Include/opcode.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Lib/importlib/_bootstrap_external.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,8 @@ def _write_atomic(path, data, mode=0o666):
# active exception)
# Python 3.11a3 3464 (bpo-45636: Merge numeric BINARY_*/INPLACE_* into
# BINARY_OP)
# Python 3.11a3 3465 (bpo-45292: PEP-654 except*)


#
# MAGIC must change whenever the bytecode emitted by the compiler may no
Expand All @@ -379,7 +381,7 @@ def _write_atomic(path, data, mode=0o666):
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
# in PC/launcher.c must also be updated.

MAGIC_NUMBER = (3464).to_bytes(2, 'little') + b'\r\n'
MAGIC_NUMBER = (3465).to_bytes(2, 'little') + b'\r\n'
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c

_PYCACHE = '__pycache__'
Expand Down
3 changes: 3 additions & 0 deletions Lib/opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ def jabs_op(name, op):
def_op('SETUP_ANNOTATIONS', 85)
def_op('YIELD_VALUE', 86)

def_op('PREP_RERAISE_STAR', 88)
def_op('POP_EXCEPT', 89)

HAVE_ARGUMENT = 90 # Opcodes from here have an argument:
Expand Down Expand Up @@ -150,6 +151,8 @@ def jabs_op(name, op):
def_op('DELETE_FAST', 126) # Local variable number
haslocal.append(126)

jabs_op('JUMP_IF_NOT_EG_MATCH', 127)

def_op('GEN_START', 129) # Kind of generator/coroutine
def_op('RAISE_VARARGS', 130) # Number of raise arguments (1, 2, or 3)
def_op('CALL_FUNCTION', 131) # #args
Expand Down
20 changes: 10 additions & 10 deletions Lib/test/test_ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -1292,22 +1292,22 @@ def test_raise(self):

def test_try(self):
p = ast.Pass()
t = ast.Try([], [], [], [p])
t = ast.Try([], [], [], [p], 0)
self.stmt(t, "empty body on Try")
t = ast.Try([ast.Expr(ast.Name("x", ast.Store()))], [], [], [p])
t = ast.Try([ast.Expr(ast.Name("x", ast.Store()))], [], [], [p], 0)
self.stmt(t, "must have Load context")
t = ast.Try([p], [], [], [])
t = ast.Try([p], [], [], [], 0)
self.stmt(t, "Try has neither except handlers nor finalbody")
t = ast.Try([p], [], [p], [p])
t = ast.Try([p], [], [p], [p], 0)
self.stmt(t, "Try has orelse but no except handlers")
t = ast.Try([p], [ast.ExceptHandler(None, "x", [])], [], [])
t = ast.Try([p], [ast.ExceptHandler(None, "x", [])], [], [], 0)
self.stmt(t, "empty body on ExceptHandler")
e = [ast.ExceptHandler(ast.Name("x", ast.Store()), "y", [p])]
self.stmt(ast.Try([p], e, [], []), "must have Load context")
self.stmt(ast.Try([p], e, [], [], 0), "must have Load context")
e = [ast.ExceptHandler(None, "x", [p])]
t = ast.Try([p], e, [ast.Expr(ast.Name("x", ast.Store()))], [p])
t = ast.Try([p], e, [ast.Expr(ast.Name("x", ast.Store()))], [p], 0)
self.stmt(t, "must have Load context")
t = ast.Try([p], e, [p], [ast.Expr(ast.Name("x", ast.Store()))])
t = ast.Try([p], e, [p], [ast.Expr(ast.Name("x", ast.Store()))], 0)
self.stmt(t, "must have Load context")

def test_assert(self):
Expand Down Expand Up @@ -2314,8 +2314,8 @@ def main():
('Module', [('With', (1, 0, 1, 17), [('withitem', ('Name', (1, 5, 1, 6), 'x', ('Load',)), ('Name', (1, 10, 1, 11), 'y', ('Store',)))], [('Pass', (1, 13, 1, 17))], None)], []),
('Module', [('With', (1, 0, 1, 25), [('withitem', ('Name', (1, 5, 1, 6), 'x', ('Load',)), ('Name', (1, 10, 1, 11), 'y', ('Store',))), ('withitem', ('Name', (1, 13, 1, 14), 'z', ('Load',)), ('Name', (1, 18, 1, 19), 'q', ('Store',)))], [('Pass', (1, 21, 1, 25))], None)], []),
('Module', [('Raise', (1, 0, 1, 25), ('Call', (1, 6, 1, 25), ('Name', (1, 6, 1, 15), 'Exception', ('Load',)), [('Constant', (1, 16, 1, 24), 'string', None)], []), None)], []),
('Module', [('Try', (1, 0, 4, 6), [('Pass', (2, 2, 2, 6))], [('ExceptHandler', (3, 0, 4, 6), ('Name', (3, 7, 3, 16), 'Exception', ('Load',)), None, [('Pass', (4, 2, 4, 6))])], [], [])], []),
('Module', [('Try', (1, 0, 4, 6), [('Pass', (2, 2, 2, 6))], [], [], [('Pass', (4, 2, 4, 6))])], []),
('Module', [('Try', (1, 0, 4, 6), [('Pass', (2, 2, 2, 6))], [('ExceptHandler', (3, 0, 4, 6), ('Name', (3, 7, 3, 16), 'Exception', ('Load',)), None, [('Pass', (4, 2, 4, 6))])], [], [], 0)], []),
('Module', [('Try', (1, 0, 4, 6), [('Pass', (2, 2, 2, 6))], [], [], [('Pass', (4, 2, 4, 6))], 0)], []),
('Module', [('Assert', (1, 0, 1, 8), ('Name', (1, 7, 1, 8), 'v', ('Load',)), None)], []),
('Module', [('Import', (1, 0, 1, 10), [('alias', (1, 7, 1, 10), 'sys', None)])], []),
('Module', [('ImportFrom', (1, 0, 1, 17), 'sys', [('alias', (1, 16, 1, 17), 'v', None)], 0)], []),
Expand Down
Loading