bpo-39562: Prevent collision of future and compiler flags (GH-19230) · python/cpython@4454057

GitHub

Original file line numberDiff line numberDiff line change@@ -832,6 +832,10 @@ Changes in the Python API

832832 inherit from it should have this method defined.

833833 (Contributed by Kyle Stanley in :issue:`34037`.)

834834835+* The constant values of future flags in the :mod:`__future__` module

836+ is updated in order to prevent collision with compiler flags. Previously

837+ ``PyCF_ALLOW_TOP_LEVEL_AWAIT`` was clashing with ``CO_FUTURE_DIVISION``.

838+ (Contributed by Batuhan Taskaya in :issue:`39562`)

835839836840CPython bytecode changes

837841------------------------

Original file line numberDiff line numberDiff line change@@ -88,19 +88,19 @@ typedef struct {

8888#defineCO_ITERABLE_COROUTINE 0x0100

8989#defineCO_ASYNC_GENERATOR 0x0200

909091-/* These are no longer used. */

92-#if0

93-#defineCO_GENERATOR_ALLOWED 0x1000

94-#endif

95-#defineCO_FUTURE_DIVISION0x2000

96-#defineCO_FUTURE_ABSOLUTE_IMPORT0x4000/* do absolute imports by default */

97-#defineCO_FUTURE_WITH_STATEMENT0x8000

98-#defineCO_FUTURE_PRINT_FUNCTION0x10000

99-#defineCO_FUTURE_UNICODE_LITERALS0x20000

100-101-#defineCO_FUTURE_BARRY_AS_BDFL0x40000

102-#defineCO_FUTURE_GENERATOR_STOP0x80000

103-#defineCO_FUTURE_ANNOTATIONS0x100000

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+#defineCO_FUTURE_DIVISION0x20000

96+#defineCO_FUTURE_ABSOLUTE_IMPORT0x40000/* do absolute imports by default */

97+#defineCO_FUTURE_WITH_STATEMENT0x80000

98+#defineCO_FUTURE_PRINT_FUNCTION0x100000

99+#defineCO_FUTURE_UNICODE_LITERALS0x200000

100+101+#defineCO_FUTURE_BARRY_AS_BDFL0x400000

102+#defineCO_FUTURE_GENERATOR_STOP0x800000

103+#defineCO_FUTURE_ANNOTATIONS0x1000000

104104105105/* This value is found in the co_cell2arg array when the associated cell

106106 variable does not correspond to an argument. */

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#definePyCF_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#definePyCF_SOURCE_IS_UTF8 0x0100

2226#definePyCF_DONT_IMPLY_DEDENT 0x0200

2327#definePyCF_ONLY_AST 0x0400

2428#definePyCF_IGNORE_COOKIE 0x0800

2529#definePyCF_TYPE_COMMENTS 0x1000

2630#definePyCF_ALLOW_TOP_LEVEL_AWAIT 0x2000

31+#definePyCF_COMPILE_MASK (PyCF_ONLY_AST | PyCF_ALLOW_TOP_LEVEL_AWAIT | \

32+ PyCF_TYPE_COMMENTS | PyCF_DONT_IMPLY_DEDENT)

27332834#ifndefPy_LIMITED_API

2935typedefstruct {

Original file line numberDiff line numberDiff line change@@ -68,14 +68,14 @@

6868# this module.

6969CO_NESTED=0x0010# nested_scopes

7070CO_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

79798080class_Feature:

8181def__init__(self, optionalRelease, mandatoryRelease, compiler_flag):

Original file line numberDiff line numberDiff line change@@ -1,5 +1,7 @@

11# Test various flavors of legal and illegal future statements

223+import__future__

4+importast

35importunittest

46fromtestimportsupport

57fromtextwrapimportdedent

@@ -75,6 +77,21 @@ def test_badfuture10(self):

7577fromtestimportbadsyntax_future10

7678self.check_syntax_error(cm.exception, "badsyntax_future10", 3)

777980+deftest_ensure_flags_dont_clash(self):

81+# bpo-39562: test that future flags and compiler flags doesn't clash

82+83+# obtain future flags (CO_FUTURE_***) from the __future__ module

84+flags= {

85+f"CO_FUTURE_{future.upper()}": getattr(__future__, future).compiler_flag

86+forfuturein__future__.all_feature_names

87+ }

88+# obtain some of the exported compiler flags (PyCF_***) from the ast module

89+flags|= {

90+flag: getattr(ast, flag)

91+forflagindir(ast) ifflag.startswith("PyCF_")

92+ }

93+self.assertCountEqual(set(flags.values()), flags.values())

94+7895deftest_parserhack(self):

7996# test that the parser.c::future_hack function works as expected

8097# Note: although this test must pass, it's not testing the original

Original file line numberDiff line numberDiff line change@@ -739,7 +739,7 @@ builtin_compile_impl(PyObject *module, PyObject *source, PyObject *filename,

739739 }

740740741741if (flags&

742- ~(PyCF_MASK | PyCF_MASK_OBSOLETE | PyCF_DONT_IMPLY_DEDENT | PyCF_ONLY_AST | PyCF_TYPE_COMMENTS))

742+ ~(PyCF_MASK | PyCF_MASK_OBSOLETE | PyCF_COMPILE_MASK))

743743 {

744744PyErr_SetString(PyExc_ValueError,

745745"compile(): unrecognised flags");