mirror of
https://github.com/davidhalter/parso.git
synced 2025-12-07 13:24:39 +08:00
Better __future__ import handling for those that don't exist.
This commit is contained in:
@@ -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')
|
_STAR_EXPR_PARENTS = ('testlist_star_expr', 'testlist_comp', 'exprlist')
|
||||||
# This is the maximal block size given by python.
|
# This is the maximal block size given by python.
|
||||||
_MAX_BLOCK_SIZE = 20
|
_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):
|
def _is_bytes_literal(string):
|
||||||
@@ -27,8 +33,10 @@ def _iter_stmts(scope):
|
|||||||
|
|
||||||
|
|
||||||
def _is_future_import(import_from):
|
def _is_future_import(import_from):
|
||||||
if import_from.level != 0:
|
# It looks like a __future__ import that is relative is still a future
|
||||||
return False
|
# import. That feels kind of odd, but whatever.
|
||||||
|
# if import_from.level != 0:
|
||||||
|
# return False
|
||||||
from_names = import_from.get_from_names()
|
from_names = import_from.get_from_names()
|
||||||
return [n.value for n in from_names] == ['__future__']
|
return [n.value for n in from_names] == ['__future__']
|
||||||
|
|
||||||
@@ -142,10 +150,22 @@ class ErrorFinder(Normalizer):
|
|||||||
yield
|
yield
|
||||||
self._context = context
|
self._context = context
|
||||||
return
|
return
|
||||||
elif node.type == 'import_from' \
|
elif node.type == 'import_from' and _is_future_import(node):
|
||||||
and _is_future_import(node) and not _is_future_import_first(node):
|
if not _is_future_import_first(node):
|
||||||
message = "from __future__ imports must occur at the beginning of the file"
|
message = "from __future__ imports must occur at the beginning of the file"
|
||||||
self._add_syntax_error(message, node)
|
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':
|
elif node.type == 'import_as_names':
|
||||||
if node.children[-1] == ',':
|
if node.children[-1] == ',':
|
||||||
# from foo import a,
|
# from foo import a,
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ gather some of the potentially dangerous ones.
|
|||||||
|
|
||||||
from __future__ import division
|
from __future__ import division
|
||||||
|
|
||||||
|
# With a dot it's not a future import anymore.
|
||||||
|
from .__future__ import absolute_import
|
||||||
|
|
||||||
'' ''
|
'' ''
|
||||||
''r''u''
|
''r''u''
|
||||||
b'' BR''
|
b'' BR''
|
||||||
|
|||||||
@@ -73,6 +73,9 @@ def test_indentation_errors(code, positions):
|
|||||||
'try: pass\nexcept: pass\nexcept X: pass',
|
'try: pass\nexcept: pass\nexcept X: pass',
|
||||||
'f(x for x in bar, 1)',
|
'f(x for x in bar, 1)',
|
||||||
'from foo import a,',
|
'from foo import a,',
|
||||||
|
'from __future__ import whatever',
|
||||||
|
'from __future__ import braces',
|
||||||
|
'from .__future__ import whatever',
|
||||||
'def f(x=3, y): pass',
|
'def f(x=3, y): pass',
|
||||||
'lambda x=3, y: x',
|
'lambda x=3, y: x',
|
||||||
#'None = 1',
|
#'None = 1',
|
||||||
|
|||||||
Reference in New Issue
Block a user