| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 8371799 commit ce6a070
14 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -752,6 +752,14 @@ iterations of the loop. | |||
| 752 | 752 | from the block stack. | |
| 753 | 753 | ||
| 754 | 754 | ||
| 755 | + .. opcode:: LOAD_ASSERTION_ERROR | ||
| 756 | + | ||
| 757 | + Pushes :exc:`AssertionError` onto the stack. Used by the :keyword:`assert` | ||
| 758 | + statement. | ||
| 759 | + | ||
| 760 | + .. versionadded:: 3.9 | ||
| 761 | + | ||
| 762 | + | ||
| 755 | 763 | .. opcode:: LOAD_BUILD_CLASS | |
| 756 | 764 | ||
| 757 | 765 | Pushes :func:`builtins.__build_class__` onto the stack. It is later called | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -226,3 +226,12 @@ Changes in the Python API | |||
| 226 | 226 | ||
| 227 | 227 | * The :mod:`venv` activation scripts no longer special-case when | |
| 228 | 228 | ``__VENV_PROMPT__`` is set to ``""``. | |
| 229 | + | ||
| 230 | + | ||
| 231 | + CPython bytecode changes | ||
| 232 | + ------------------------ | ||
| 233 | + | ||
| 234 | + * The :opcode:`LOAD_ASSERTION_ERROR` opcode was added for handling the | ||
| 235 | + :keyword:`assert` statement. Previously, the assert statement would not work | ||
| 236 | + correctly if the :exc:`AssertionError` exception was being shadowed. | ||
| 237 | + (Contributed by Zackery Spytz in :issue:`34880`.) | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -271,6 +271,7 @@ def _write_atomic(path, data, mode=0o666): | |||
| 271 | 271 | # Python 3.8b2 3412 (Swap the position of positional args and positional | |
| 272 | 272 | # only args in ast.arguments #37593) | |
| 273 | 273 | # Python 3.8b4 3413 (Fix "break" and "continue" in "finally" #37830) | |
| 274 | + # Python 3.9a0 3420 (add LOAD_ASSERTION_ERROR #34880) | ||
| 274 | 275 | # | |
| 275 | 276 | # MAGIC must change whenever the bytecode emitted by the compiler may no | |
| 276 | 277 | # longer be understood by older implementations of the eval loop (usually | |
@@ -279,7 +280,7 @@ def _write_atomic(path, data, mode=0o666): | |||
| 279 | 280 | # Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array | |
| 280 | 281 | # in PC/launcher.c must also be updated. | |
| 281 | 282 | ||
| 282 | - MAGIC_NUMBER = (3413).to_bytes(2, 'little') + b'\r\n' | ||
| 283 | + MAGIC_NUMBER = (3420).to_bytes(2, 'little') + b'\r\n' | ||
| 283 | 284 | _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c | |
| 284 | 285 | ||
| 285 | 286 | _PYCACHE = '__pycache__' | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -109,7 +109,7 @@ def jabs_op(name, op): | |||
| 109 | 109 | def_op('LOAD_BUILD_CLASS', 71) | |
| 110 | 110 | def_op('YIELD_FROM', 72) | |
| 111 | 111 | def_op('GET_AWAITABLE', 73) | |
| 112 | - | ||
| 112 | + def_op('LOAD_ASSERTION_ERROR', 74) | ||
| 113 | 113 | def_op('INPLACE_LSHIFT', 75) | |
| 114 | 114 | def_op('INPLACE_RSHIFT', 76) | |
| 115 | 115 | def_op('INPLACE_AND', 77) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -147,7 +147,7 @@ def bug1333982(x=[]): | |||
| 147 | 147 | dis_bug1333982 = """\ | |
| 148 | 148 | %3d 0 LOAD_CONST 1 (0) | |
| 149 | 149 | 2 POP_JUMP_IF_TRUE 26 | |
| 150 | - 4 LOAD_GLOBAL 0 (AssertionError) | ||
| 150 | + 4 LOAD_ASSERTION_ERROR | ||
| 151 | 151 | 6 LOAD_CONST 2 (<code object <listcomp> at 0x..., file "%s", line %d>) | |
| 152 | 152 | 8 LOAD_CONST 3 ('bug1333982.<locals>.<listcomp>') | |
| 153 | 153 | 10 MAKE_FUNCTION 0 | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1285,6 +1285,22 @@ def g(): | |||
| 1285 | 1285 | next(i) | |
| 1286 | 1286 | next(i) | |
| 1287 | 1287 | ||
| 1288 | + @unittest.skipUnless(__debug__, "Won't work if __debug__ is False") | ||
| 1289 | + def test_assert_shadowing(self): | ||
| 1290 | + # Shadowing AssertionError would cause the assert statement to | ||
| 1291 | + # misbehave. | ||
| 1292 | + global AssertionError | ||
| 1293 | + AssertionError = TypeError | ||
| 1294 | + try: | ||
| 1295 | + assert False, 'hello' | ||
| 1296 | + except BaseException as e: | ||
| 1297 | + del AssertionError | ||
| 1298 | + self.assertIsInstance(e, AssertionError) | ||
| 1299 | + self.assertEqual(str(e), 'hello') | ||
| 1300 | + else: | ||
| 1301 | + del AssertionError | ||
| 1302 | + self.fail('Expected exception') | ||
| 1303 | + | ||
| 1288 | 1304 | ||
| 1289 | 1305 | class ImportErrorTests(unittest.TestCase): | |
| 1290 | 1306 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,3 @@ | |||
| 1 | + The :keyword:`assert` statement now works properly if the | ||
| 2 | + :exc:`AssertionError` exception is being shadowed. | ||
| 3 | + Patch by Zackery Spytz. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2242,6 +2242,13 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) | |||
| 2242 | 2242 | } | |
| 2243 | 2243 | } | |
| 2244 | 2244 | ||
| 2245 | + case TARGET(LOAD_ASSERTION_ERROR): { | ||
| 2246 | + PyObject *value = PyExc_AssertionError; | ||
| 2247 | + Py_INCREF(value); | ||
| 2248 | + PUSH(value); | ||
| 2249 | + FAST_DISPATCH(); | ||
| 2250 | + } | ||
| 2251 | + | ||
| 2245 | 2252 | case TARGET(LOAD_BUILD_CLASS): { | |
| 2246 | 2253 | _Py_IDENTIFIER(__build_class__); | |
| 2247 | 2254 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1129,6 +1129,8 @@ stack_effect(int opcode, int oparg, int jump) | |||
| 1129 | 1129 | return (oparg & FVS_MASK) == FVS_HAVE_SPEC ? -1 : 0; | |
| 1130 | 1130 | case LOAD_METHOD: | |
| 1131 | 1131 | return 1; | |
| 1132 | + case LOAD_ASSERTION_ERROR: | ||
| 1133 | + return 1; | ||
| 1132 | 1134 | default: | |
| 1133 | 1135 | return PY_INVALID_STACK_EFFECT; | |
| 1134 | 1136 | } | |
@@ -3253,16 +3255,10 @@ compiler_from_import(struct compiler *c, stmt_ty s) | |||
| 3253 | 3255 | static int | |
| 3254 | 3256 | compiler_assert(struct compiler *c, stmt_ty s) | |
| 3255 | 3257 | { | |
| 3256 | - static PyObject *assertion_error = NULL; | ||
| 3257 | 3258 | basicblock *end; | |
| 3258 | 3259 | ||
| 3259 | 3260 | if (c->c_optimize) | |
| 3260 | 3261 | return 1; | |
| 3261 | - if (assertion_error == NULL) { | ||
| 3262 | - assertion_error = PyUnicode_InternFromString("AssertionError"); | ||
| 3263 | - if (assertion_error == NULL) | ||
| 3264 | - return 0; | ||
| 3265 | - } | ||
| 3266 | 3262 | if (s->v.Assert.test->kind == Tuple_kind && | |
| 3267 | 3263 | asdl_seq_LEN(s->v.Assert.test->v.Tuple.elts) > 0) | |
| 3268 | 3264 | { | |
@@ -3277,7 +3273,7 @@ compiler_assert(struct compiler *c, stmt_ty s) | |||
| 3277 | 3273 | return 0; | |
| 3278 | 3274 | if (!compiler_jump_if(c, s->v.Assert.test, end, 1)) | |
| 3279 | 3275 | return 0; | |
| 3280 | - ADDOP_O(c, LOAD_GLOBAL, assertion_error, names); | ||
| 3276 | + ADDOP(c, LOAD_ASSERTION_ERROR); | ||
| 3281 | 3277 | if (s->v.Assert.msg) { | |
| 3282 | 3278 | VISIT(c, expr, s->v.Assert.msg); | |
| 3283 | 3279 | ADDOP_I(c, CALL_FUNCTION, 1); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments