8000 [3.8] bpo-39562: Prevent collision of future and compiler flags (GH-1… · python/cpython@5055c27 · GitHub
[go: up one dir, main page]

Skip to content
10000

Commit 5055c27

Browse files
[3.8] bpo-39562: Prevent collision of future and compiler flags (GH-19230) (GH-19835)
The constant values of future flags in the __future__ module is updated in order to prevent collision with compiler flags. Previously PyCF_ALLOW_TOP_LEVEL_AWAIT was clashing with CO_FUTURE_DIVISION.. (cherry picked from commit 4454057) Co-authored-by: Batuhan Taşkaya <batuhanosmantaskaya@gmail.com>
1 parent 95e208d commit 5055c27

File tree

7 files changed

+53
-22
lines changed

7 files changed

+53
-22
lines changed

Doc/whatsnew/3.8.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2234,3 +2234,8 @@ Notable changes in Python 3.8.2
22342234
Fixed a regression with the ``ignore`` callback of :func:`shutil.copytree`.
22352235
The argument types are now str and List[str] again.
22362236
(Contributed by Manuel Barkhau and Giampaolo Rodola in :issue:`39390`.)
2237+
2238+
The constant values of future flags in the :mod:`__future__` module
2239+
are updated in order to prevent collision with compiler flags. Previously
2240+
``PyCF_ALLOW_TOP_LEVEL_AWAIT`` was clashing with ``CO_FUTURE_DIVISION``.
2241+
(Contributed by Batuhan Taskaya in :issue:`39562`)

Include/code.h

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -88,19 +88,19 @@ typedef struct {
8888
#define CO_ITERABLE_COROUTINE 0x0100
8989
#define CO_ASYNC_GENERATOR 0x0200
9090

91-
/* These are no longer used. */
92-
#if 0
93-
#define CO_GENERATOR_ALLOWED 0x1000
94-
#endif
95-
#define CO_FUTURE_DIVISION 0x2000
96-
#define CO_FUTURE_ABSOLUTE_IMPORT 0x4000 /* do absolute imports by default */
97-
#define CO_FUTURE_WITH_STATEMENT 0x8000
98-
#define CO_FUTURE_PRINT_FUNCTION 0x10000
99-
#define CO_FUTURE_UNICODE_LITERALS 0x20000
100-
101-
#define CO_FUTURE_BARRY_AS_BDFL 0x40000
102-
#define CO_FUTURE_GENERATOR_STOP 0x80000
103-
#define CO_FUTURE_ANNOTATIONS 0x100000
91+
/* bpo-39562: These constant values are changed in Python 3.9
92+
to prevent collision with compiler flags. CO_FUTURE_ and PyCF_
93+
constants must be kept unique. PyCF_ constants can use bits from
94+
0x0100 to 0x10000. CO_FUTURE_ constants use bits starting at 0x20000. */
95+
#define CO_FUTURE_DIVISION 0x20000
96+
#define CO_FUTURE_ABSOLUTE_IMPORT 0x40000 /* do absolute imports by default */
97+
#define CO_FUTURE_WITH_STATEMENT 0x80000
98+
#define CO_FUTURE_PRINT_FUNCTION 0x100000
99+
#define CO_FUTURE_UNICODE_LITERALS 0x200000
100+
101+
#define CO_FUTURE_BARRY_AS_BDFL 0x400000
102+
#define CO_FUTURE_GENERATOR_STOP 0x800000
103+
#define CO_FUTURE_ANNOTATIONS 0x1000000
104104

105105
/* This value is found in the co_cell2arg array when the associated cell
106106
variable does not correspond to an argument. */

Include/compile.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,18 @@ PyAPI_FUNC(PyCodeObject *) PyNode_Compile(struct _node *, const char *);
1818
CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL | \
1919
CO_FUTURE_GENERATOR_STOP | CO_FUTURE_ANNOTATIONS)
2020
#define PyCF_MASK_OBSOLETE (CO_NESTED)
21+
22+
/* bpo-39562: CO_FUTURE_ and PyCF_ constants must be kept unique.
23+
PyCF_ constants can use bits from 0x0100 to 0x10000.
24+
CO_FUTURE_ constants use bits starting at 0x20000. */
2125
#define PyCF_SOURCE_IS_UTF8 0x0100
2226
#define PyCF_DONT_IMPLY_DEDENT 0x0200
2327
#define PyCF_ONLY_AST 0x0400
2428
#define PyCF_IGNORE_COOKIE 0x0800
2529
#define PyCF_TYPE_COMMENTS 0x1000
2630
#define PyCF_ALLOW_TOP_LEVEL_AWAIT 0x2000
31+
#define PyCF_COMPILE_MASK (PyCF_ONLY_AST | PyCF_ALLOW_TOP_LEVEL_AWAIT | \
32+
PyCF_TYPE_COMMENTS | PyCF_DONT_IMPLY_DEDENT)
2733

2834
#ifndef Py_LIMITED_API
2935
typedef struct {

Lib/__future__.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,14 @@
6868
# this module.
6969
CO_NESTED = 0x0010 # nested_scopes
7070
CO_GENERATOR_ALLOWED = 0 # generators (obsolete, was 0x1000)
71-
CO_FUTURE_DIVISION = 0x2000 # division
72-
CO_FUTURE_ABSOLUTE_IMPORT = 0x4000 # perform absolute imports by default
73-
CO_FUTURE_WITH_STATEMENT = 0x8000 # with statement
74-
CO_FUTURE_PRINT_FUNCTION = 0x10000 # print function
75-
CO_FUTURE_UNICODE_LITERALS = 0x20000 # unicode string literals
76-
CO_FUTURE_BARRY_AS_BDFL = 0x40000
77-
CO_FUTURE_GENERATOR_STOP = 0x80000 # StopIteration becomes RuntimeError in generators
78-
CO_FUTURE_ANNOTATIONS = 0x100000 # annotations become strings at runtime
71+
CO_FUTURE_DIVISION = 0x20000 # division
72+
CO_FUTURE_ABSOLUTE_IMPORT = 0x40000 # perform absolute imports by default
73+
CO_FUTURE_WITH_STATEMENT = 0x80000 # with statement
74+
CO_FUTURE_PRINT_FUNCTION = 0x100000 # print function
75+
CO_FUTURE_UNICODE_LITERALS = 0x200000 # unicode string literals
76+
CO_FUTURE_BARRY_AS_BDFL = 0x400000
77+
CO_FUTURE_GENERATOR_STOP = 0x800000 # StopIteration becomes RuntimeError in generators
78+
CO_FUTURE_ANNOTATIONS = 0x1000000 # annotations become strings at runtime
7979

8080
class _Feature:
8181
def __init__(self, optionalRelease, mandatoryRelease, compiler_flag):

Lib/test/test_future.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Test various flavors of legal and illegal future statements
22

3+
import __future__
4+
import ast
35
import unittest
46
from test import support
57
from textwrap import dedent
@@ -74,6 +76,21 @@ def test_badfuture10(self):
7476
from test import badsyntax_future10
7577
self.check_syntax_error(cm.exception, "badsyntax_future10", 3)
7678

79+
def test_ensure_flags_dont_clash(self):
80+
# bpo-39562: test that future flags and compiler flags doesn't clash
81+
82+
# obtain future flags (CO_FUTURE_***) from the __future__ module
83+
flags = {
84+
f"CO_FUTURE_{future.upper()}": getattr(__future__, future).compiler_flag
85+
for future in __future__.all_feature_names
86+
}
87+
# obtain some of the exported compiler flags (PyCF_***) from the ast module
88+
flags.update({
89+
flag: getattr(ast, flag)
90+
for flag in dir(ast) if flag.startswith("PyCF_")
91+
})
92+
self.assertCountEqual(set(flags.values()), flags.values())
93+
7794
def test_parserhack(self):
7895
# test that the parser.c::future_hack function works as expected
7996
# Note: although this test must pass, it's not testing the original
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
The constant values of future flags in the :mod:`__future__` module are
2+
updated in order to prevent collision with compiler flags. Previously
3+
``PyCF_ALLOW_TOP_LEVEL_AWAIT`` was clashing with ``CO_FUTURE_DIVISION``.

Python/bltinmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,7 @@ builtin_compile_impl(PyObject *module, PyObject *source, PyObject *filename,
738738
}
739739

740740
if (flags &
741-
~(PyCF_MASK | PyCF_MASK_OBSOLETE | PyCF_DONT_IMPLY_DEDENT | PyCF_ONLY_AST | PyCF_TYPE_COMMENTS))
741+
~(PyCF_MASK | PyCF_MASK_OBSOLETE | PyCF_COMPILE_MASK))
742742
{
743743
PyErr_SetString(PyExc_ValueError,
744744
"compile(): unrecognised flags");

0 commit comments

Comments
 (0)
0