Skip to content

Commit b82da9e

Browse files
[3.6] bpo-27169: The __debug__ constant is now optimized out at compile time. (GH-4880) (#4882)
This fixes also bpo-22091.. (cherry picked from commit 3325a67)
1 parent 22097aa commit b82da9e

File tree

4 files changed

+26
-38
lines changed

4 files changed

+26
-38
lines changed

Lib/test/test_builtin.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -331,16 +331,16 @@ def test_compile(self):
331331
try:
332332
assert False
333333
except AssertionError:
334-
return (True, f.__doc__)
334+
return (True, f.__doc__, __debug__)
335335
else:
336-
return (False, f.__doc__)
336+
return (False, f.__doc__, __debug__)
337337
'''
338338
def f(): """doc"""
339-
values = [(-1, __debug__, f.__doc__),
340-
(0, True, 'doc'),
341-
(1, False, 'doc'),
342-
(2, False, None)]
343-
for optval, debugval, docstring in values:
339+
values = [(-1, __debug__, f.__doc__, __debug__),
340+
(0, True, 'doc', True),
341+
(1, False, 'doc', False),
342+
(2, False, None, False)]
343+
for optval, *expected in values:
344344
# test both direct compilation and compilation via AST
345345
codeobjs = []
346346
codeobjs.append(compile(codestr, "<test>", "exec", optimize=optval))
@@ -350,7 +350,7 @@ def f(): """doc"""
350350
ns = {}
351351
exec(code, ns)
352352
rv = ns['f']()
353-
self.assertEqual(rv, (debugval, docstring))
353+
self.assertEqual(rv, tuple(expected))
354354

355355
def test_delattr(self):
356356
sys.spam = 1

Lib/test/test_compile.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ def test_debug_assignment(self):
3535
import builtins
3636
prev = builtins.__debug__
3737
setattr(builtins, '__debug__', 'sure')
38+
self.assertEqual(__debug__, prev)
3839
setattr(builtins, '__debug__', prev)
3940

4041
def test_argument_handling(self):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
The ``__debug__`` constant is now optimized out at compile time. This fixes also
2+
bpo-22091.

Python/compile.c

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,13 +1343,15 @@ is_const(expr_ty e)
13431343
case Ellipsis_kind:
13441344
case NameConstant_kind:
13451345
return 1;
1346+
case Name_kind:
1347+
return _PyUnicode_EqualToASCIIString(e->v.Name.id, "__debug__");
13461348
default:
13471349
return 0;
13481350
}
13491351
}
13501352

13511353
static PyObject *
1352-
get_const_value(expr_ty e)
1354+
get_const_value(struct compiler *c, expr_ty e)
13531355
{
13541356
switch (e->kind) {
13551357
case Constant_kind:
@@ -1364,6 +1366,9 @@ get_const_value(expr_ty e)
13641366
return Py_Ellipsis;
13651367
case NameConstant_kind:
13661368
return e->v.NameConstant.value;
1369+
case Name_kind:
1370+
assert(_PyUnicode_EqualToASCIIString(e->v.Name.id, "__debug__"));
1371+
return c->c_optimize ? Py_False : Py_True;
13671372
default:
13681373
assert(!is_const(e));
13691374
return NULL;
@@ -3035,6 +3040,11 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx)
30353040
!_PyUnicode_EqualToASCIIString(name, "True") &&
30363041
!_PyUnicode_EqualToASCIIString(name, "False"));
30373042

3043+
if (ctx == Load && _PyUnicode_EqualToASCIIString(name, "__debug__")) {
3044+
ADDOP_O(c, LOAD_CONST, c->c_optimize ? Py_False : Py_True, consts);
3045+
return 1;
3046+
}
3047+
30383048
op = 0;
30393049
optype = OP_NAME;
30403050
scope = PyST_GetScope(c->u->u_ste, mangled);
@@ -3298,7 +3308,7 @@ compiler_subdict(struct compiler *c, expr_ty e, Py_ssize_t begin, Py_ssize_t end
32983308
return 0;
32993309
}
33003310
for (i = begin; i < end; i++) {
3301-
key = get_const_value((expr_ty)asdl_seq_GET(e->v.Dict.keys, i));
3311+
key = get_const_value(c, (expr_ty)asdl_seq_GET(e->v.Dict.keys, i));
33023312
Py_INCREF(key);
33033313
PyTuple_SET_ITEM(keys, i - begin, key);
33043314
}
@@ -4044,35 +4054,10 @@ compiler_visit_keyword(struct compiler *c, keyword_ty k)
40444054
static int
40454055
expr_constant(struct compiler *c, expr_ty e)
40464056
{
4047-
char *id;
4048-
switch (e->kind) {
4049-
case Ellipsis_kind:
4050-
return 1;
4051-
case Constant_kind:
4052-
return PyObject_IsTrue(e->v.Constant.value);
4053-
case Num_kind:
4054-
return PyObject_IsTrue(e->v.Num.n);
4055-
case Str_kind:
4056-
return PyObject_IsTrue(e->v.Str.s);
4057-
case Name_kind:
4058-
/* optimize away names that can't be reassigned */
4059-
id = PyUnicode_AsUTF8(e->v.Name.id);
4060-
if (id && strcmp(id, "__debug__") == 0)
4061-
return !c->c_optimize;
4062-
return -1;
4063-
case NameConstant_kind: {
4064-
PyObject *o = e->v.NameConstant.value;
4065-
if (o == Py_None)
4066-
return 0;
4067-
else if (o == Py_True)
4068-
return 1;
4069-
else if (o == Py_False)
4070-
return 0;
4071-
}
4072-
/* fall through */
4073-
default:
4074-
return -1;
4057+
if (is_const(e)) {
4058+
return PyObject_IsTrue(get_const_value(c, e));
40754059
}
4060+
return -1;
40764061
}
40774062

40784063

0 commit comments

Comments
 (0)