Patchwork [2,of,3,STABLE] check-code: detect incorrect format operation on the string not including "%"

login
register
mail settings
Submitter Katsunori FUJIWARA
Date April 13, 2014, 1:32 p.m.
Message ID <98b776640d7939e3a8d6.1397395938@feefifofum>
Download mbox | patch
Permalink /patch/4313/
State Superseded
Headers show

Comments

Katsunori FUJIWARA - April 13, 2014, 1:32 p.m.
# HG changeset patch
# User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
# Date 1397394948 -32400
#      Sun Apr 13 22:15:48 2014 +0900
# Branch stable
# Node ID 98b776640d7939e3a8d6ac6601d5c7cd173c0539
# Parent  6c252c9898beaedcf3230741445310b0071e5cb4
check-code: detect incorrect format operation on the string not including "%"

This patch introduces new patterns to detect incorrect format
operations on the string not including any "%" specifiers: it causes
TypeError at runtime.

Patterns newly introduced by this patch treat format operations in
"(format-string) % value" style. This mainly focuses on format
operations applied on the value returned from "_()".

To aware "%" in strings, this patch prevents "repquote()" from
normalizing "%" into another character.

Patch

diff --git a/contrib/check-code.py b/contrib/check-code.py
--- a/contrib/check-code.py
+++ b/contrib/check-code.py
@@ -44,7 +44,7 @@ 
         if i > 255:
             return 'u'
         c = chr(i)
-        if c in ' \n':
+        if c in ' \n%':
             return c
         if c.isalpha():
             return 'x'
@@ -200,6 +200,10 @@ 
     (r'\S;\s*\n', "semicolon"),
     (r'[^_]_\([ \t\n]*(?:"[^"]+"[ \t\n+]*)+%', "don't use % inside _()"),
     (r"[^_]_\([ \t\n]*(?:'[^']+'[ \t\n+]*)+%", "don't use % inside _()"),
+    (r'\([ \t\n]*(?:"(?:[^%"]|%%)+"[ \t\n+]*)+\)[ \t\n]*%',
+     "don't apply % on non-format string"),
+    (r"\([ \t\n]*(?:'(?:[^%']|%%)+'[ \t\n+]*)+\)[ \t\n]*%",
+     "don't apply % on non-format string"),
     (r'(\w|\)),\w', "missing whitespace after ,"),
     (r'(\w|\))[+/*\-<>]\w', "missing whitespace in expression"),
     (r'^\s+(\w|\.)+=\w[^,()\n]*$', "missing whitespace in assignment"),
diff --git a/mercurial/obsolete.py b/mercurial/obsolete.py
--- a/mercurial/obsolete.py
+++ b/mercurial/obsolete.py
@@ -369,7 +369,7 @@ 
         repo.ui.warn(_('unknown key: %r') % key)
         return 0
     if old:
-        repo.ui.warn(_('unexpected old value') % key)
+        repo.ui.warn(_('unexpected old value for %r') % key)
         return 0
     data = base85.b85decode(new)
     lock = repo.lock()
diff --git a/tests/test-check-code.t b/tests/test-check-code.t
--- a/tests/test-check-code.t
+++ b/tests/test-check-code.t
@@ -251,3 +251,31 @@ 
    warning: add two newlines after '.. note::'
   [1]
 
+  $ cat > ./invalid-formatting.py <<EOF
+  > print ("no percent character") % v
+  > print ("no "
+  >        "percent"
+  >        "character") % v
+  > print (
+  >        "no " +
+  >        "percent" +
+  >        "character") % v
+  > print ("%% doesn't work as percent") % v
+  > 
+  > print ("ambiguous case, %% and %s") % v
+  > print ("ambiguous case (", " %Y-%M-%D")
+  > EOF
+  $ "$check_code" ./invalid-formatting.py
+  ./invalid-formatting.py:1:
+   > print ("no percent character") % v
+   don't apply % on non-format string
+  ./invalid-formatting.py:2:
+   > print ("no "
+   don't apply % on non-format string
+  ./invalid-formatting.py:5:
+   > print (
+   don't apply % on non-format string
+  ./invalid-formatting.py:9:
+   > print ("%% doesn't work as percent") % v
+   don't apply % on non-format string
+  [1]