Better __future__ import handling for those that don't exist.

This commit is contained in:
Dave Halter
2017-07-25 20:21:38 +02:00
parent d012353637
commit 6a92f5ec2d
3 changed files with 32 additions and 6 deletions

View File

@@ -6,6 +6,12 @@ _BLOCK_STMTS = ('if_stmt', 'while_stmt', 'for_stmt', 'try_stmt', 'with_stmt')
_STAR_EXPR_PARENTS = ('testlist_star_expr', 'testlist_comp', 'exprlist')
# This is the maximal block size given by python.
_MAX_BLOCK_SIZE = 20
ALLOWED_FUTURES = (
'all_feature_names', 'nested_scopes', 'generators', 'division',
'absolute_import', 'with_statement', 'print_function', 'unicode_literals',
# TODO make this one optional in lower python versions.
'generator_stop'
)
def _is_bytes_literal(string):
@@ -27,8 +33,10 @@ def _iter_stmts(scope):
def _is_future_import(import_from):
if import_from.level != 0:
return False
# It looks like a __future__ import that is relative is still a future
# import. That feels kind of odd, but whatever.
# if import_from.level != 0:
# return False
from_names = import_from.get_from_names()
return [n.value for n in from_names] == ['__future__']
@@ -142,10 +150,22 @@ class ErrorFinder(Normalizer):
yield
self._context = context
return
elif node.type == 'import_from' \
and _is_future_import(node) and not _is_future_import_first(node):
message = "from __future__ imports must occur at the beginning of the file"
self._add_syntax_error(message, node)
elif node.type == 'import_from' and _is_future_import(node):
if not _is_future_import_first(node):
message = "from __future__ imports must occur at the beginning of the file"
self._add_syntax_error(message, node)
for from_name, future_name in node.get_paths():
name = future_name.value
if name== 'braces':
message = "not a chance"
self._add_syntax_error(message, node)
elif name == 'barry_as_FLUFL':
message = "Seriously I'm not implementing this :) ~ Dave"
self._add_syntax_error(message, node)
elif name not in ALLOWED_FUTURES:
message = "future feature %s is not defined" % name
self._add_syntax_error(message, node)
elif node.type == 'import_as_names':
if node.children[-1] == ',':
# from foo import a,

View File

@@ -5,6 +5,9 @@ gather some of the potentially dangerous ones.
from __future__ import division
# With a dot it's not a future import anymore.
from .__future__ import absolute_import
'' ''
''r''u''
b'' BR''

View File

@@ -73,6 +73,9 @@ def test_indentation_errors(code, positions):
'try: pass\nexcept: pass\nexcept X: pass',
'f(x for x in bar, 1)',
'from foo import a,',
'from __future__ import whatever',
'from __future__ import braces',
'from .__future__ import whatever',
'def f(x=3, y): pass',
'lambda x=3, y: x',
#'None = 1',