summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Behnel <stefan_ml@behnel.de>2018-08-25 10:28:49 +0200
committerStefan Behnel <stefan_ml@behnel.de>2018-09-16 12:31:10 +0200
commitc8e6f375dab5589ea2441775e193d650119dc9b2 (patch)
tree5791a19678fae5b6dc94d543531e18f5cbae9861
parente59d4dcf6c93e8e4c330bca57cbad90476776531 (diff)
downloadcython-c8e6f375dab5589ea2441775e193d650119dc9b2.tar.gz
Warn when no "language_level" is specified to prepare the transition to language_level=3.
Closes #2593.
-rw-r--r--Cython/Compiler/Main.py15
-rw-r--r--Cython/Compiler/Options.py3
-rw-r--r--Cython/Compiler/Parsing.py11
-rw-r--r--Cython/Compiler/Scanning.py4
-rw-r--r--Cython/Compiler/TreeFragment.py3
-rwxr-xr-xruntests.py4
-rwxr-xr-xsetup.py3
7 files changed, 31 insertions, 12 deletions
diff --git a/Cython/Compiler/Main.py b/Cython/Compiler/Main.py
index 8867b1bd5..411ef0a8f 100644
--- a/Cython/Compiler/Main.py
+++ b/Cython/Compiler/Main.py
@@ -67,9 +67,10 @@ class Context(object):
# language_level int currently 2 or 3 for Python 2/3
cython_scope = None
+ language_level = None # warn when not set but default to Py2
def __init__(self, include_directories, compiler_directives, cpp=False,
- language_level=2, options=None):
+ language_level=None, options=None):
# cython_scope is a hack, set to False by subclasses, in order to break
# an infinite loop.
# Better code organization would fix it.
@@ -91,7 +92,8 @@ class Context(object):
os.path.join(os.path.dirname(__file__), os.path.pardir, 'Includes')))
self.include_directories = include_directories + [standard_include_path]
- self.set_language_level(language_level)
+ if language_level is not None:
+ self.set_language_level(language_level)
self.gdb_debug_outputwriter = None
@@ -548,9 +550,10 @@ class CompilationOptions(object):
', '.join(unknown_options))
raise ValueError(message)
+ directive_defaults = Options.get_directive_defaults()
directives = dict(options['compiler_directives']) # copy mutable field
# check for invalid directives
- unknown_directives = set(directives) - set(Options.get_directive_defaults())
+ unknown_directives = set(directives) - set(directive_defaults)
if unknown_directives:
message = "got unknown compiler directive%s: %s" % (
's' if len(unknown_directives) > 1 else '',
@@ -562,7 +565,9 @@ class CompilationOptions(object):
warnings.warn("C++ mode forced when in Pythran mode!")
options['cplus'] = True
if 'language_level' in directives and 'language_level' not in kw:
- options['language_level'] = int(directives['language_level'])
+ options['language_level'] = directives['language_level']
+ elif not options.get('language_level'):
+ options['language_level'] = directive_defaults.get('language_level')
if 'formal_grammar' in directives and 'formal_grammar' not in kw:
options['formal_grammar'] = directives['formal_grammar']
if options['cache'] is True:
@@ -824,7 +829,7 @@ default_options = dict(
emit_linenums = False,
relative_path_in_code_position_comments = True,
c_line_in_traceback = True,
- language_level = 2,
+ language_level = None, # warn but default to 2
formal_grammar = False,
gdb_debug = False,
compile_time_env = None,
diff --git a/Cython/Compiler/Options.py b/Cython/Compiler/Options.py
index 3d640a73f..4b9f3805c 100644
--- a/Cython/Compiler/Options.py
+++ b/Cython/Compiler/Options.py
@@ -197,7 +197,7 @@ _directive_defaults = {
'autotestdict': True,
'autotestdict.cdef': False,
'autotestdict.all': False,
- 'language_level': 2,
+ 'language_level': None,
'fast_getattr': False, # Undocumented until we come up with a better way to handle this everywhere.
'py2_import': False, # For backward compatibility of Cython's source code in Py3 source mode
'preliminary_late_includes_cy28': False, # Temporary directive in 0.28, to be removed in a later version (see GH#2079).
@@ -299,6 +299,7 @@ def normalise_encoding_name(option_name, encoding):
# Override types possibilities above, if needed
directive_types = {
+ 'language_level': int, # values can be None/2/3, where None == 2+warning
'auto_pickle': bool,
'final' : bool, # final cdef classes and methods
'internal' : bool, # cdef class visibility in the module dict
diff --git a/Cython/Compiler/Parsing.py b/Cython/Compiler/Parsing.py
index ad2d21240..dde1c3b8f 100644
--- a/Cython/Compiler/Parsing.py
+++ b/Cython/Compiler/Parsing.py
@@ -3662,6 +3662,17 @@ def p_module(s, pxd, full_module_name, ctx=Ctx):
directive_comments = p_compiler_directive_comments(s)
s.parse_comments = False
+ if s.context.language_level is None:
+ s.context.set_language_level(2)
+ if pos[0].filename:
+ import warnings
+ warnings.warn(
+ "Cython directive 'language_level' not set, using 2 for now (Py2). "
+ "This will change in a later release! File: %s" % pos[0].filename,
+ FutureWarning,
+ stacklevel=1 if cython.compiled else 2,
+ )
+
doc = p_doc_string(s)
if pxd:
level = 'module_pxd'
diff --git a/Cython/Compiler/Scanning.py b/Cython/Compiler/Scanning.py
index 9e07aa0eb..466384b4e 100644
--- a/Cython/Compiler/Scanning.py
+++ b/Cython/Compiler/Scanning.py
@@ -147,6 +147,8 @@ class SourceDescriptor(object):
"""
A SourceDescriptor should be considered immutable.
"""
+ filename = None
+
_file_type = 'pyx'
_escaped_description = None
@@ -274,8 +276,6 @@ class StringSourceDescriptor(SourceDescriptor):
Instances of this class can be used instead of a filenames if the
code originates from a string object.
"""
- filename = None
-
def __init__(self, name, code):
self.name = name
#self.set_file_type_from_name(name)
diff --git a/Cython/Compiler/TreeFragment.py b/Cython/Compiler/TreeFragment.py
index 30dc19553..b85da8191 100644
--- a/Cython/Compiler/TreeFragment.py
+++ b/Cython/Compiler/TreeFragment.py
@@ -29,7 +29,8 @@ class StringParseContext(Main.Context):
include_directories = []
if compiler_directives is None:
compiler_directives = {}
- Main.Context.__init__(self, include_directories, compiler_directives, cpp=cpp)
+ # TODO: see if "language_level=3" also works for our internal code here.
+ Main.Context.__init__(self, include_directories, compiler_directives, cpp=cpp, language_level=2)
self.module_name = name
def find_module(self, module_name, relative_to=None, pos=None, need_pxd=1, absolute_fallback=True):
diff --git a/runtests.py b/runtests.py
index 217a0458f..837d306e4 100755
--- a/runtests.py
+++ b/runtests.py
@@ -2295,8 +2295,8 @@ def runtests(options, cmd_args, coverage=None):
sys.stderr.write("Disabling forked testing to support XML test output\n")
options.fork = False
- if WITH_CYTHON and options.language_level == 3:
- sys.stderr.write("Using Cython language level 3.\n")
+ if WITH_CYTHON:
+ sys.stderr.write("Using Cython language level %d.\n" % options.language_level)
test_bugs = False
if options.tickets:
diff --git a/setup.py b/setup.py
index f44f33e8c..a94fc0d39 100755
--- a/setup.py
+++ b/setup.py
@@ -156,8 +156,9 @@ def compile_cython_modules(profile=False, compile_more=False, cython_with_refnan
extensions[-1].sources[0] = pyx_source_file
from Cython.Distutils.build_ext import new_build_ext
+ from Cython.Compiler.Options import get_directive_defaults
+ get_directive_defaults()['language_level'] = 2
if profile:
- from Cython.Compiler.Options import get_directive_defaults
get_directive_defaults()['profile'] = True
sys.stderr.write("Enabled profiling for the Cython binary modules\n")