From de65e601655b8841a363865ee3d7acfd2c866d67 Mon Sep 17 00:00:00 2001 From: David Fisher Date: Thu, 1 Dec 2016 15:13:25 -0800 Subject: [PATCH] Make string interpolation checking less unnecessarily permissive --- mypy/checkstrformat.py | 8 +++----- test-data/unit/check-expressions.test | 7 +++++++ test-data/unit/fixtures/python2.pyi | 8 +++++++- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/mypy/checkstrformat.py b/mypy/checkstrformat.py index ddf69c264c4ca..fec7d251622f1 100644 --- a/mypy/checkstrformat.py +++ b/mypy/checkstrformat.py @@ -151,13 +151,11 @@ def check_simple_str_interpolation(self, specifiers: List[ConversionSpecifier], def check_mapping_str_interpolation(self, specifiers: List[ConversionSpecifier], replacements: Expression) -> None: - if (isinstance(replacements, DictExpr) and - all(isinstance(k, (StrExpr, BytesExpr)) - for k, v in replacements.items)): + if isinstance(replacements, DictExpr): mapping = {} # type: Dict[str, Type] for k, v in replacements.items: - key_str = cast(StrExpr, k).value - mapping[key_str] = self.accept(v) + if isinstance(k, (StrExpr, BytesExpr, UnicodeExpr)): + mapping[k.value] = self.accept(v) for specifier in specifiers: if specifier.type == '%': diff --git a/test-data/unit/check-expressions.test b/test-data/unit/check-expressions.test index e6fbbf092c86b..3c0d56f58ff27 100644 --- a/test-data/unit/check-expressions.test +++ b/test-data/unit/check-expressions.test @@ -1083,9 +1083,16 @@ a = None # type: Any '%(a)d' % {'a': 1, 'b': 2, 'c': 3} '%(q)d' % {'a': 1, 'b': 2, 'c': 3} # E: Key 'q' not found in mapping '%(a)d %%' % {'a': 1} +'%(q)d' % {'a': 1, 'b': 2, 0: 3} # E: Key 'q' not found in mapping [builtins fixtures/dict.pyi] +[case testStringInterpolationMappingKeys_python2] +'%(q)d' % {u'a': 1, 'b': 2, 'c': 3} # E: Key 'q' not found in mapping +'%(a)d' % {u'a': 1, 'b': 2, 'c': 3} + +[builtins_py2 fixtures/python2.pyi] + [case testStringInterpolationMappingDictTypes] from typing import Any, Dict a = None # type: Any diff --git a/test-data/unit/fixtures/python2.pyi b/test-data/unit/fixtures/python2.pyi index 61e48be4510e7..dd60331f99c76 100644 --- a/test-data/unit/fixtures/python2.pyi +++ b/test-data/unit/fixtures/python2.pyi @@ -1,4 +1,4 @@ -from typing import Generic, Iterable, TypeVar +from typing import Generic, Iterable, Mapping, TypeVar class object: def __init__(self) -> None: pass @@ -9,10 +9,16 @@ class type: class function: pass class int: pass +class float: pass class str: pass class unicode: pass +class tuple: pass T = TypeVar('T') class list(Iterable[T], Generic[T]): pass +KT = TypeVar('KT') +VT = TypeVar('VT') +class dict(Iterable[KT], Mapping[KT, VT], Generic[KT, VT]): pass + # Definition of None is implicit