diff --git a/mypy/fastparse2.py b/mypy/fastparse2.py index 6b2f8d562156..1f8ffda457ea 100644 --- a/mypy/fastparse2.py +++ b/mypy/fastparse2.py @@ -148,6 +148,7 @@ def __init__(self, self.options = options self.is_stub = is_stub self.errors = errors + self.unicode_literals = False def fail(self, msg: str, line: int, column: int) -> None: self.errors.report(line, column, msg) @@ -653,6 +654,8 @@ def visit_ImportFrom(self, n: ast27.ImportFrom) -> ImportBase: n.level, [(a.name, a.asname) for a in n.names]) self.imports.append(i) + if n.module == '__future__' and any(nm.name == 'unicode_literals' for nm in n.names): + self.unicode_literals = True return i # Global(identifier* names) @@ -880,6 +883,8 @@ def visit_Str(self, s: ast27.Str) -> Expression: contents = str(n)[2:-1] return StrExpr(contents) else: + if self.unicode_literals and all(ord(c) < 128 for c in s.s): # ASCII only + return StrExpr(s.s) return UnicodeExpr(s.s) # Ellipsis diff --git a/test-data/unit/python2eval.test b/test-data/unit/python2eval.test index b750de8b12a1..df94be932d13 100644 --- a/test-data/unit/python2eval.test +++ b/test-data/unit/python2eval.test @@ -151,15 +151,39 @@ f(**params) [out] [case testFromFutureImportUnicodeLiterals2_python2] +# coding=utf-8 from __future__ import unicode_literals def f(x): # type: (str) -> None pass f(b'') -f(u'') -f('') +f(u'щось') +f('щось інше') [out] -_program.py:5: error: Argument 1 to "f" has incompatible type "unicode"; expected "str" _program.py:6: error: Argument 1 to "f" has incompatible type "unicode"; expected "str" +_program.py:7: error: Argument 1 to "f" has incompatible type "unicode"; expected "str" + +[case testUnicodeLiteralsFutureImportAllASCII_python2] +# coding=utf-8 +from __future__ import unicode_literals +x = None # type: str +x = 'не латиниця' # Error +x = 'only ascii' # This is however OK +reveal_type('another ascii') +[out] +_program.py:4: error: Incompatible types in assignment (expression has type "unicode", variable has type "str") +_program.py:6: error: Revealed type is 'builtins.str' + +[case testUnicodeLiteralsFutureImportAllASCIIvariant1_python2] +from __future__ import absolute_import, unicode_literals +x = None # type: str +x = 'only ascii' +[out] + +[case testUnicodeLiteralsFutureImportAllASCIIvariant2_python2] +from __future__ import unicode_literals as something_else +x = None # type: str +x = 'only ascii' +[out] [case testStrUnicodeCompatibility_python2] import typing