From f987c8f587bd645a1b15c8f7b17b98de1d63d174 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 12 Aug 2014 22:15:39 +0400 Subject: [PATCH] PY-11274 Check right operand of format operator using abc.Mapping interface --- .../inspections/PyStringFormatInspection.java | 5 +++-- .../src/string-format.py | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/python/src/com/jetbrains/python/inspections/PyStringFormatInspection.java b/python/src/com/jetbrains/python/inspections/PyStringFormatInspection.java index 162fa0b9bc60..40efca3663a0 100644 --- a/python/src/com/jetbrains/python/inspections/PyStringFormatInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyStringFormatInspection.java @@ -41,6 +41,7 @@ import java.util.Map; import static com.jetbrains.python.inspections.PyStringFormatParser.filterSubstitutions; import static com.jetbrains.python.inspections.PyStringFormatParser.parsePercentFormat; +import static com.jetbrains.python.psi.PyUtil.as; /** * @author Alexey.Ivanov @@ -416,9 +417,9 @@ public class PyStringFormatInspection extends PyInspection { inspectValues(((PyParenthesizedExpression)rightExpression).getContainedExpression()); } else { - final PyType type = myTypeEvalContext.getType(rightExpression); + final PyClassType type = as(myTypeEvalContext.getType(rightExpression), PyClassType.class); if (type != null) { - if (myUsedMappingKeys.size() > 0 && !("dict".equals(type.getName()))) { + if (myUsedMappingKeys.size() > 0 && !PyABCUtil.isSubclass(type.getPyClass(), PyNames.MAPPING)) { registerProblem(rightExpression, PyBundle.message("INSP.format.requires.mapping")); return; } diff --git a/python/testData/inspections/PyStringFormatInspection/src/string-format.py b/python/testData/inspections/PyStringFormatInspection/src/string-format.py index b82ebcf4eb5c..972aaed6423a 100644 --- a/python/testData/inspections/PyStringFormatInspection/src/string-format.py +++ b/python/testData/inspections/PyStringFormatInspection/src/string-format.py @@ -102,4 +102,20 @@ print '%d, %d, %d, %d' % my_tuple[:7:3] print '%d %s' % ((42,) + ('spam',)) print '%d %s' % (('ham',) + ('spam',)) print '%d %s' % ((42,) + ()) -print '%d' % ((42,) + ('spam',)) \ No newline at end of file +print '%d' % ((42,) + ('spam',)) + +# PY-11274 +import collections +print '%(foo)s' % collections.OrderedDict(foo=None) + +class MyDict(collections.Mapping): + def __getitem__(self, key): + return 'spam' + + def __iter__(self): + yield 'spam' + + def __len__(self): + return 1 + +print '%(foo)s' % MyDict()