From 8c5ea6ecc02ef852e18d822f15e68ac059e1779d Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Tue, 15 Dec 2015 20:50:23 +0300 Subject: [PATCH] Converted PyStringFormatInspection tests into hightlighing-based tests --- .../PyStringFormatInspection/Basic.py | 127 ++++++++++++ .../DictionaryArgument.py | 9 + .../Slice.py} | 2 +- .../TupleMultiplication.py | 5 + .../PyStringFormatInspection/expected.xml | 189 ------------------ .../src/string-format.py | 126 ------------ .../PyStringFormatInspection1/test.py | 16 -- .../python/PythonInspectionsTest.java | 13 -- .../PyStringFormatInspectionTest.java | 50 +++++ 9 files changed, 192 insertions(+), 345 deletions(-) create mode 100644 python/testData/inspections/PyStringFormatInspection/Basic.py create mode 100644 python/testData/inspections/PyStringFormatInspection/DictionaryArgument.py rename python/testData/inspections/{PyStringFormatInspectionSlice/test.py => PyStringFormatInspection/Slice.py} (93%) create mode 100644 python/testData/inspections/PyStringFormatInspection/TupleMultiplication.py delete mode 100644 python/testData/inspections/PyStringFormatInspection/expected.xml delete mode 100644 python/testData/inspections/PyStringFormatInspection/src/string-format.py delete mode 100644 python/testData/inspections/PyStringFormatInspection1/test.py create mode 100644 python/testSrc/com/jetbrains/python/inspections/PyStringFormatInspectionTest.java diff --git a/python/testData/inspections/PyStringFormatInspection/Basic.py b/python/testData/inspections/PyStringFormatInspection/Basic.py new file mode 100644 index 000000000000..368d82fb4bd5 --- /dev/null +++ b/python/testData/inspections/PyStringFormatInspection/Basic.py @@ -0,0 +1,127 @@ +'#%(language)s has %(#)03d quote types.' % {'language': "Python", "#": 2} #ok +'%d %s' % 5 #Too few arguments for format string +'Hello world' % 25 #Too many arguments for format string +"%(name)f(name)" % {'name': 23.2} #ok +"%()s" % {'': "name"} #ok +'test%(name)' % {'name': 23} #There are no format specifier character +'work%*d' % (2, 34) #ok +'work%(name)*d' % (12, 32) #Can't use '*' in formats when using a mapping +'%*.*d' % (2, 5, 5) #ok +'%*.*d' % (2, 4) #Too few arguments for format string +'%*.*d' % (2, 4, 5, 6) #Too many arguments for format string +'%**d' % (2, 5) #There are no format specifier character +'%(name1)s %(name2)s (name3) %s' % {'name1': 'a', 'name2': 'b', 'name3': 'c'} #Too few mapping keys +'%(name1s' % {'name1': 'a'} #Too few mapping keys +'%%%(name)ld' % {'name': 12} #ok +"%(name)f(name)" % 23.2 #Format requires a mapping +"%(name)f(name)" % (23.2) #Format requires a mapping +'%d%d' % {'name1': 2, 'name2': 3} #Format doesn't require a mapping +'%12.2f' % 2.74 #ok +'Hello world' % () #ok +'Hello world' % [] #ok +'Hello world' % {} #ok +'%d%d' % ((5), (5)) #ok +"%(name)d %(name)d" % {"name": 43} #ok +"%(name)d" % {'a': 4, "name": 5} #ok +'%% name %(name)c' % {'a': 4} #Key 'name' has no following argument +'%d %u %f %F %s %r' % (2, 3, 4.1, 4.0, "name", "str") #ok +'%d %d %d' % (4, "a", "b") #Unexpected type +'%f %f %f' % (4, 5, "test") #Unexpected type +'%d' % "name" #Unexpected type +m = {'language': "Python", "#": 2} +'#%(language)s has %(#)03d quote types.' % m #ok +i = "test" +'%(name)s' % {'name': i} #ok +'%s' % i #ok +'%f' % i #Unexpected type +'%f' % (2 * 3 + 5) #ok +s = "%s" % "a".upper() #ok +x = ['a', 'b', 'c'] +print "%d: %s" % (len(x), ", ".join(x)) #ok +m = [1, 2, 3, 4, 5] +"%d" % m[0] #ok +"%d %s" % (m[0], m[4]) #ok +"%s" % m #ok +"%s" % m[1:3] #ok +"%d" % m[1:2] #ok +"%d" % m #Unexpected type +"%d" % [] #Unexpected type +def greet(all): + print "Hello %s" % ("World" if all else "Human") #ok +"%s" % [x + 1 for x in [1, 2, 3, 4]] #ok +"%s" % [x + y for x in []] #ok +"%s" % [] #ok +"%f" % [x + 1 for x in [1, 2, 3, 4]] #Unexpected type +"%d %d" % (3, 5) #ok +"Hello %s %s" % tuple(['world', '!']) #ok + +def foo(a): + if a == 1: + return "a", "b" + else: + return "c", "d" +print "%s" % foo(1) #Too many arguments for format string + +print("| [%(issue_id)s|http://youtrack.jetbrains.net/issue/%(issue_id)s] (%(issue_type)s)|%(summary)s|" % (issue_id, issue_type, summary)) #Format requires a mapping (PY-704) + +my_list = list() +for i in range(0,3): + my_list.append( ("hey", "you") ) + +for item in my_list: + print '%s %s' % item # ok (PY-734) + +def bar(): + return None +"%s %s" % bar() #Too few arguments for format string + +"%s" % {} # ok; str() works +"%s" % {'a': 1, 'b': 2} # ok, no names in template and arg counts don't match +"%s" % object() # ok, str() works +"foo" % {'bar':1, 'baz':2} # ok: empty template that could use names + +a = ('a', 1) if 1 else ('b', 2) +"%s is %d" % a # ok, must infer unified tuple type +#PY-3064, because original type of a is tuple, not list +a = (1,2,3) +print '%d:%d' % a[:2] +print '%d:%d' % a[1:2] + +string = "qwerty" +print '%d:%d' % string[:2] +print '%s:%s' % string[:2] +print '%s' % string[:2] +print '%d' % string[:2] + +my_tuple = (1,2,3,4,5,6,7,8) +print '%d, %d' % my_tuple[:7:3] +print '%d, %d, %d' % my_tuple[:7:3] +print '%d, %d, %d, %d' % my_tuple[:7:3] + +# PY-12801 +print '%d %s' % ((42,) + ('spam',)) +print '%d %s' % (('ham',) + ('spam',)) +print '%d %s' % ((42,) + ()) +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() + +foo = {1, 2, 3} +print('%s %s %s' % foo) + +'%s %s %s' % (x for x in range(10)) + diff --git a/python/testData/inspections/PyStringFormatInspection/DictionaryArgument.py b/python/testData/inspections/PyStringFormatInspection/DictionaryArgument.py new file mode 100644 index 000000000000..57afe539b09f --- /dev/null +++ b/python/testData/inspections/PyStringFormatInspection/DictionaryArgument.py @@ -0,0 +1,9 @@ +my_dict = {'class': 3} + +my_dict['css_class'] = "" +if my_dict['class']: + my_dict['css_class'] = 'class %(class)s' % my_dict + +my_dict['tmp'] = 'classes %(css_class)s' % my_dict + +my_dict['tmp'] = 'classes %(claz)s' % my_dict diff --git a/python/testData/inspections/PyStringFormatInspectionSlice/test.py b/python/testData/inspections/PyStringFormatInspection/Slice.py similarity index 93% rename from python/testData/inspections/PyStringFormatInspectionSlice/test.py rename to python/testData/inspections/PyStringFormatInspection/Slice.py index 8ef36b1ed699..a179d40db68e 100644 --- a/python/testData/inspections/PyStringFormatInspectionSlice/test.py +++ b/python/testData/inspections/PyStringFormatInspection/Slice.py @@ -1,5 +1,5 @@ def foo(x): - return x + return x artist = foo(1) print('%s' % (artist.lower()[0:10])) diff --git a/python/testData/inspections/PyStringFormatInspection/TupleMultiplication.py b/python/testData/inspections/PyStringFormatInspection/TupleMultiplication.py new file mode 100644 index 000000000000..616ea22ef9d5 --- /dev/null +++ b/python/testData/inspections/PyStringFormatInspection/TupleMultiplication.py @@ -0,0 +1,5 @@ +argument_pattern = re.compile(r'(%s)\s*(\(\s*(%s)\s*\)\s*)?$' + % ((states.Inliner.simplename,) * 2)) + +t, num = ('foo',), 2 +res = '%d %d' % (t * num) diff --git a/python/testData/inspections/PyStringFormatInspection/expected.xml b/python/testData/inspections/PyStringFormatInspection/expected.xml deleted file mode 100644 index c9e8b5f55532..000000000000 --- a/python/testData/inspections/PyStringFormatInspection/expected.xml +++ /dev/null @@ -1,189 +0,0 @@ - - - - string-format.py - 2 - Too few arguments for format string - - - string-format.py - 3 - Too many arguments for format string - - - string-format.py - 6 - Format specifier character missing - - - string-format.py - 8 - Can't use '*' in formats when using a mapping - - - string-format.py - 10 - Too few arguments for format string - - - string-format.py - 11 - Too many arguments for format string - - - string-format.py - 12 - Format specifier character missing - - - string-format.py - 13 - Too few mapping keys - - - string-format.py - 14 - Too few mapping keys - - - string-format.py - 16 - Format requires a mapping - - - string-format.py - 17 - Format requires a mapping - - - string-format.py - 18 - Format doesn't require a mapping - - - string-format.py - 26 - Key 'name' has no following argument - - - string-format.py - 28 - Unexpected type - - - string-format.py - 28 - Unexpected type - - - string-format.py - 29 - Unexpected type - - - string-format.py - 30 - Unexpected type - - - string-format.py - 36 - Unexpected type - - - string-format.py - 46 - Unexpected type - - - string-format.py - 47 - Unexpected type - - - string-format.py - 48 - Unexpected type - - - string-format.py - 54 - Unexpected type - - - string-format.py - 63 - Too many arguments for format string - - - string-format.py - 65 - Format requires a mapping - - - string-format.py - 76 - Too few arguments for format string - - - string-format.py - 88 - Too few arguments for format string - - - string-format.py - 91 - Too few arguments for format string - - - string-format.py - 91 - Unexpected type - - - string-format.py - 92 - Too few arguments for format string - - - string-format.py - 94 - Unexpected type - - - string-format.py - 97 - Too many arguments for format string - - - string-format.py - 99 - Too few arguments for format string - - - string-format.py - 103 - Unexpected type - - - string-format.py - 104 - Too few arguments for format string - - - string-format.py - 105 - Too many arguments for format string - - - string-format.py - 124 - Too few arguments for format string - - - string-format.py - 126 - Too few arguments for format string - - - diff --git a/python/testData/inspections/PyStringFormatInspection/src/string-format.py b/python/testData/inspections/PyStringFormatInspection/src/string-format.py deleted file mode 100644 index 16bfe73814a1..000000000000 --- a/python/testData/inspections/PyStringFormatInspection/src/string-format.py +++ /dev/null @@ -1,126 +0,0 @@ -'#%(language)s has %(#)03d quote types.' % {'language': "Python", "#": 2} #ok -'%d %s' % 5 #Too few arguments for format string -'Hello world' % 25 #Too many arguments for format string -"%(name)f(name)" % {'name': 23.2} #ok -"%()s" % {'': "name"} #ok -'test%(name)' % {'name': 23} #There are no format specifier character -'work%*d' % (2, 34) #ok -'work%(name)*d' % (12, 32) #Can't use '*' in formats when using a mapping -'%*.*d' % (2, 5, 5) #ok -'%*.*d' % (2, 4) #Too few arguments for format string -'%*.*d' % (2, 4, 5, 6) #Too many arguments for format string -'%**d' % (2, 5) #There are no format specifier character -'%(name1)s %(name2)s (name3) %s' % {'name1': 'a', 'name2': 'b', 'name3': 'c'} #Too few mapping keys -'%(name1s' % {'name1': 'a'} #Too few mapping keys -'%%%(name)ld' % {'name': 12} #ok -"%(name)f(name)" % 23.2 #Format requires a mapping -"%(name)f(name)" % (23.2) #Format requires a mapping -'%d%d' % {'name1': 2, 'name2': 3} #Format doesn't require a mapping -'%12.2f' % 2.74 #ok -'Hello world' % () #ok -'Hello world' % [] #ok -'Hello world' % {} #ok -'%d%d' % ((5), (5)) #ok -"%(name)d %(name)d" % {"name": 43} #ok -"%(name)d" % {'a': 4, "name": 5} #ok -'%% name %(name)c' % {'a': 4} #Key 'name' has no following argument -'%d %u %f %F %s %r' % (2, 3, 4.1, 4.0, "name", "str") #ok -'%d %d %d' % (4, "a", "b") #Unexpected type -'%f %f %f' % (4, 5, "test") #Unexpected type -'%d' % "name" #Unexpected type -m = {'language': "Python", "#": 2} -'#%(language)s has %(#)03d quote types.' % m #ok -i = "test" -'%(name)s' % {'name': i} #ok -'%s' % i #ok -'%f' % i #Unexpected type -'%f' % (2 * 3 + 5) #ok -s = "%s" % "a".upper() #ok -x = ['a', 'b', 'c'] -print "%d: %s" % (len(x), ", ".join(x)) #ok -m = [1, 2, 3, 4, 5] -"%d" % m[0] #ok -"%d %s" % (m[0], m[4]) #ok -"%s" % m #ok -"%s" % m[1:3] #ok -"%d" % m[1:2] #ok -"%d" % m #Unexpected type -"%d" % [] #Unexpected type -def greet(all): - print "Hello %s" % ("World" if all else "Human") #ok -"%s" % [x + 1 for x in [1, 2, 3, 4]] #ok -"%s" % [x + y for x in []] #ok -"%s" % [] #ok -"%f" % [x + 1 for x in [1, 2, 3, 4]] #Unexpected type -"%d %d" % (3, 5) #ok -"Hello %s %s" % tuple(['world', '!']) #ok - -def foo(a): - if a == 1: - return "a", "b" - else: - return "c", "d" -print "%s" % foo(1) #Too many arguments for format string - -print("| [%(issue_id)s|http://youtrack.jetbrains.net/issue/%(issue_id)s] (%(issue_type)s)|%(summary)s|" % (issue_id, issue_type, summary)) #Format requires a mapping (PY-704) - -my_list = list() -for i in range(0,3): - my_list.append( ("hey", "you") ) - -for item in my_list: - print '%s %s' % item # ok (PY-734) - -def bar(): - return None -"%s %s" % bar() #Too few arguments for format string - -"%s" % {} # ok; str() works -"%s" % {'a': 1, 'b': 2} # ok, no names in template and arg counts don't match -"%s" % object() # ok, str() works -"foo" % {'bar':1, 'baz':2} # ok: empty template that could use names - -a = ('a', 1) if 1 else ('b', 2) -"%s is %d" % a # ok, must infer unified tuple type -#PY-3064, because original type of a is tuple, not list -a = (1,2,3) -print '%d:%d' % a[:2] -print '%d:%d' % a[1:2] - -string = "qwerty" -print '%d:%d' % string[:2] -print '%s:%s' % string[:2] -print '%s' % string[:2] -print '%d' % string[:2] - -my_tuple = (1,2,3,4,5,6,7,8) -print '%d, %d' % my_tuple[:7:3] -print '%d, %d, %d' % my_tuple[:7:3] -print '%d, %d, %d, %d' % my_tuple[:7:3] - -# PY-12801 -print '%d %s' % ((42,) + ('spam',)) -print '%d %s' % (('ham',) + ('spam',)) -print '%d %s' % ((42,) + ()) -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() - -foo = {1, 2, 3} -print('%s %s %s' % foo) - -'%s %s %s' % (x for x in range(10)) diff --git a/python/testData/inspections/PyStringFormatInspection1/test.py b/python/testData/inspections/PyStringFormatInspection1/test.py deleted file mode 100644 index 92212324a230..000000000000 --- a/python/testData/inspections/PyStringFormatInspection1/test.py +++ /dev/null @@ -1,16 +0,0 @@ -my_dict = {'class': 3} - -my_dict['css_class'] = "" -if my_dict['class']: - my_dict['css_class'] = 'class %(class)s' % my_dict - -my_dict['tmp'] = 'classes %(css_class)s' % my_dict - -my_dict['tmp'] = 'classes %(claz)s' % my_dict - -#PY-4647 -argument_pattern = re.compile(r'(%s)\s*(\(\s*(%s)\s*\)\s*)?$' - % ((states.Inliner.simplename,) * 2)) - -t, num = ('foo',), 2 -res = '%d %d' % (t * num) \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java b/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java index b85751460054..721d76be818b 100644 --- a/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java +++ b/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java @@ -70,11 +70,6 @@ public class PythonInspectionsTest extends PyTestCase { doHighlightingTest(PyRedeclarationInspection.class); } - public void testPyStringFormatInspection() { - LocalInspectionTool inspection = new PyStringFormatInspection(); - doTest(getTestName(false), inspection); - } - public void testPyTrailingSemicolonInspection() { LocalInspectionTool inspection = new PyTrailingSemicolonInspection(); doTest(getTestName(false), inspection); @@ -287,14 +282,6 @@ public class PythonInspectionsTest extends PyTestCase { doHighlightingTest(PyListCreationInspection.class); } - public void testPyStringFormatInspection1() { //PY-2836 - doHighlightingTest(PyStringFormatInspection.class); - } - - public void testPyStringFormatInspectionSlice() { //PY-6756 - doHighlightingTest(PyStringFormatInspection.class); - } - public void testPyUnnecessaryBackslashInspection() { //PY-2952 setLanguageLevel(LanguageLevel.PYTHON27); doHighlightingTest(PyUnnecessaryBackslashInspection.class); diff --git a/python/testSrc/com/jetbrains/python/inspections/PyStringFormatInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyStringFormatInspectionTest.java new file mode 100644 index 000000000000..af787e153a46 --- /dev/null +++ b/python/testSrc/com/jetbrains/python/inspections/PyStringFormatInspectionTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jetbrains.python.inspections; + +import com.jetbrains.python.fixtures.PyTestCase; + +/** + * @author vlan + */ +public class PyStringFormatInspectionTest extends PyTestCase { + public static final String TEST_DIRECTORY = "inspections/PyStringFormatInspection/"; + + public void testBasic() { + doTest(); + } + + // PY-2836 + public void testDictionaryArgument() { + doTest(); + } + + // PY-4647 + public void testTupleMultiplication() { + doTest(); + } + + // PY-6756 + public void testSlice() { + doTest(); + } + + private void doTest() { + myFixture.configureByFile(TEST_DIRECTORY + getTestName(false) + ".py"); + myFixture.enableInspections(PyStringFormatInspection.class); + myFixture.checkHighlighting(true, false, true); + } +}