Skip to content

Commit 3325a67

Browse files
bpo-27169: The __debug__ constant is now optimized out at compile time. (#4880)
This fixes also bpo-22091.
1 parent 297fd87 commit 3325a67

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
@@ -337,16 +337,16 @@ def test_compile(self):
337337
try:
338338
assert False
339339
except AssertionError:
340-
return (True, f.__doc__, debug_enabled)
340+
return (True, f.__doc__, debug_enabled, __debug__)
341341
else:
342-
return (False, f.__doc__, debug_enabled)
342+
return (False, f.__doc__, debug_enabled, __debug__)
343343
'''
344344
def f(): """doc"""
345-
values = [(-1, __debug__, f.__doc__, __debug__),
346-
(0, True, 'doc', True),
347-
(1, False, 'doc', False),
348-
(2, False, None, False)]
349-
for optval, assertval, docstring, debugval in values:
345+
values = [(-1, __debug__, f.__doc__, __debug__, __debug__),
346+
(0, True, 'doc', True, True),
347+
(1, False, 'doc', False, False),
348+
(2, False, None, False, False)]
349+
for optval, *expected in values:
350350
# test both direct compilation and compilation via AST
351351
codeobjs = []
352352
codeobjs.append(compile(codestr, "<test>", "exec", optimize=optval))
@@ -356,7 +356,7 @@ def f(): """doc"""
356356
ns = {}
357357
exec(code, ns)
358358
rv = ns['f']()
359-
self.assertEqual(rv, (assertval, docstring, debugval))
359+
self.assertEqual(rv, tuple(expected))
360360

361361
def test_delattr(self):
362362
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
@@ -1332,13 +1332,15 @@ is_const(expr_ty e)
13321332
case Ellipsis_kind:
13331333
case NameConstant_kind:
13341334
return 1;
1335+
case Name_kind:
1336+
return _PyUnicode_EqualToASCIIString(e->v.Name.id, "__debug__");
13351337
default:
13361338
return 0;
13371339
}
13381340
}
13391341

13401342
static PyObject *
1341-
get_const_value(expr_ty e)
1343+
get_const_value(struct compiler *c, expr_ty e)
13421344
{
13431345
switch (e->kind) {
13441346
case Constant_kind:
@@ -1353,6 +1355,9 @@ get_const_value(expr_ty e)
13531355
return Py_Ellipsis;
13541356
case NameConstant_kind:
13551357
return e->v.NameConstant.value;
1358+
case Name_kind:
1359+
assert(_PyUnicode_EqualToASCIIString(e->v.Name.id, "__debug__"));
1360+
return c->c_optimize ? Py_False : Py_True;
13561361
default:
13571362
Py_UNREACHABLE();
13581363
}
@@ -3097,6 +3102,11 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx)
30973102
!_PyUnicode_EqualToASCIIString(name, "True") &&
30983103
!_PyUnicode_EqualToASCIIString(name, "False"));
30993104

3105+
if (ctx == Load && _PyUnicode_EqualToASCIIString(name, "__debug__")) {
3106+
ADDOP_O(c, LOAD_CONST, c->c_optimize ? Py_False : Py_True, consts);
3107+
return 1;
3108+
}
3109+
31003110
op = 0;
31013111
optype = OP_NAME;
31023112
scope = PyST_GetScope(c->u->u_ste, mangled);
@@ -3360,7 +3370,7 @@ compiler_subdict(struct compiler *c, expr_ty e, Py_ssize_t begin, Py_ssize_t end
33603370
return 0;
33613371
}
33623372
for (i = begin; i < end; i++) {
3363-
key = get_const_value((expr_ty)asdl_seq_GET(e->v.Dict.keys, i));
3373+
key = get_const_value(c, (expr_ty)asdl_seq_GET(e->v.Dict.keys, i));
33643374
Py_INCREF(key);
33653375
PyTuple_SET_ITEM(keys, i - begin, key);
33663376
}
@@ -4132,35 +4142,10 @@ compiler_visit_keyword(struct compiler *c, keyword_ty k)
41324142
static int
41334143
expr_constant(struct compiler *c, expr_ty e)
41344144
{
4135-
const char *id;
4136-
switch (e->kind) {
4137-
case Ellipsis_kind:
4138-
return 1;
4139-
case Constant_kind:
4140-
return PyObject_IsTrue(e->v.Constant.value);
4141-
case Num_kind:
4142-
return PyObject_IsTrue(e->v.Num.n);
4143-
case Str_kind:
4144-
return PyObject_IsTrue(e->v.Str.s);
4145-
case Name_kind:
4146-
/* optimize away names that can't be reassigned */
4147-
id = PyUnicode_AsUTF8(e->v.Name.id);
4148-
if (id && strcmp(id, "__debug__") == 0)
4149-
return !c->c_optimize;
4150-
return -1;
4151-
case NameConstant_kind: {
4152-
PyObject *o = e->v.NameConstant.value;
4153-
if (o == Py_None)
4154-
return 0;
4155-
else if (o == Py_True)
4156-
return 1;
4157-
else if (o == Py_False)
4158-
return 0;
4159-
}
4160-
/* fall through */
4161-
default:
4162-
return -1;
4145+
if (is_const(e)) {
4146+
return PyObject_IsTrue(get_const_value(c, e));
41634147
}
4148+
return -1;
41644149
}
41654150

41664151

0 commit comments

Comments
 (0)