Add support for 'from __future__ import annotations'

PEP 563 brought a new `__future__` import for post-poning evaluation
of annotations that introduced in 3.7. This patch adds support for
that future feature, and removes 'all_feature_names' from that list
since it is not valid a syntax
(`from __future__ import all_feature_names`). Also it fixes a bug
related usage of `ALLOWED_FUTURES` (global and version independant
flags) instead of `allowed_futures` (extended version of the previ
ous flag that has some version specific flags, probably unnoticed)
This commit is contained in:
Batuhan Taskaya
2020-05-22 17:07:55 +03:00
parent 34b8b7dd79
commit 261132e74c
2 changed files with 10 additions and 6 deletions

View File

@@ -13,8 +13,8 @@ _STAR_EXPR_PARENTS = ('testlist_star_expr', 'testlist_comp', 'exprlist')
_MAX_BLOCK_SIZE = 20 _MAX_BLOCK_SIZE = 20
_MAX_INDENT_COUNT = 100 _MAX_INDENT_COUNT = 100
ALLOWED_FUTURES = ( ALLOWED_FUTURES = (
'all_feature_names', 'nested_scopes', 'generators', 'division', 'nested_scopes', 'generators', 'division', 'absolute_import',
'absolute_import', 'with_statement', 'print_function', 'unicode_literals', 'with_statement', 'print_function', 'unicode_literals',
) )
_COMP_FOR_TYPES = ('comp_for', 'sync_comp_for') _COMP_FOR_TYPES = ('comp_for', 'sync_comp_for')
@@ -622,13 +622,14 @@ class _FutureImportRule(SyntaxRule):
allowed_futures = list(ALLOWED_FUTURES) allowed_futures = list(ALLOWED_FUTURES)
if self._normalizer.version >= (3, 5): if self._normalizer.version >= (3, 5):
allowed_futures.append('generator_stop') allowed_futures.append('generator_stop')
if self._normalizer.version >= (3, 7):
allowed_futures.append('annotations')
if name == 'braces': if name == 'braces':
self.add_issue(node, message="not a chance") self.add_issue(node, message="not a chance")
elif name == 'barry_as_FLUFL': elif name == 'barry_as_FLUFL':
m = "Seriously I'm not implementing this :) ~ Dave" m = "Seriously I'm not implementing this :) ~ Dave"
self.add_issue(node, message=m) self.add_issue(node, message=m)
elif name not in ALLOWED_FUTURES: elif name not in allowed_futures:
message = "future feature %s is not defined" % name message = "future feature %s is not defined" % name
self.add_issue(node, message=message) self.add_issue(node, message=message)

View File

@@ -185,12 +185,13 @@ def test_statically_nested_blocks():
def test_future_import_first(): def test_future_import_first():
def is_issue(code, *args): def is_issue(code, *args, **kwargs):
code = code % args code = code % args
return bool(_get_error_list(code)) return bool(_get_error_list(code, **kwargs))
i1 = 'from __future__ import division' i1 = 'from __future__ import division'
i2 = 'from __future__ import absolute_import' i2 = 'from __future__ import absolute_import'
i3 = 'from __future__ import annotations'
assert not is_issue(i1) assert not is_issue(i1)
assert not is_issue(i1 + ';' + i2) assert not is_issue(i1 + ';' + i2)
assert not is_issue(i1 + '\n' + i2) assert not is_issue(i1 + '\n' + i2)
@@ -201,6 +202,8 @@ def test_future_import_first():
assert not is_issue('""\n%s;%s', i1, i2) assert not is_issue('""\n%s;%s', i1, i2)
assert not is_issue('"";%s;%s ', i1, i2) assert not is_issue('"";%s;%s ', i1, i2)
assert not is_issue('"";%s\n%s ', i1, i2) assert not is_issue('"";%s\n%s ', i1, i2)
assert not is_issue(i3, version="3.7")
assert is_issue(i3, version="3.6")
assert is_issue('1;' + i1) assert is_issue('1;' + i1)
assert is_issue('1\n' + i1) assert is_issue('1\n' + i1)
assert is_issue('"";1\n' + i1) assert is_issue('"";1\n' + i1)