closes #113231. logging checker now looks at instances of Logger classes in addition to the base logging module.

authorMike Bryant <leachim@leachim.info>
changeset27d5a6ff3ea8
branchdefault
phasepublic
hiddenno
parent revision#dc6a12f97c9a disable R0924 here to fix test_regr.test_gtk_import
child revision#720a5ebaba7d string check: don't warn about octal escape sequence, warn about \o (not octal in python). Closes #111799
files modified by this revision
ChangeLog
checkers/logging.py
test/input/func_bug113231.py
test/messages/func_bug113231.txt
# HG changeset patch
# User Mike Bryant <leachim@leachim.info>
# Date 1354815877 0
# Thu Dec 06 17:44:37 2012 +0000
# Node ID 27d5a6ff3ea8c51a263381c59306b66a7be2e2aa
# Parent dc6a12f97c9a9fb6c9a5fc3db545e66ed6d28528
closes #113231. logging checker now looks at instances of Logger classes in addition to the base logging module.

diff --git a/ChangeLog b/ChangeLog
@@ -22,10 +22,13 @@
1        and useless suppression pragmas. (patch by Torsten Marek)
2 
3      * #112728: Add warning E0604 for non-string objects in __all__
4        (patch by Torsten Marek)
5 
6 +    * #113231: logging checker now looks at instances of Logger classes
7 +      in addition to the base logging module. (patch by Mike Bryant)
8 +
9  --
10      * #115580: fix erroneous W0212 (access to protected member) on super call
11        (patch by Martin Pool)
12 
13      * #110853: fix a crash when an __init__ method in a base class has been
diff --git a/checkers/logging.py b/checkers/logging.py
@@ -78,12 +78,21 @@
14                      self._logging_name = 'logging'
15 
16      def visit_callfunc(self, node):
17          """Checks calls to (simple forms of) logging methods."""
18          if (not isinstance(node.func, astng.Getattr)
19 -            or not isinstance(node.func.expr, astng.Name)
20 -            or node.func.expr.name != self._logging_name):
21 +            or not isinstance(node.func.expr, astng.Name)):
22 +            return
23 +        try:
24 +            logger_class = [inferred for inferred in node.func.expr.infer() if (
25 +                isinstance(inferred, astng.Instance)
26 +                and [ancestor for ancestor in inferred._proxied.ancestors() if (
27 +                    ancestor.name == 'Logger'
28 +                    and ancestor.parent.name == 'logging')])]
29 +        except astng.exceptions.InferenceError:
30 +            return
31 +        if (node.func.expr.name != self._logging_name and not logger_class):
32              return
33          self._check_convenience_methods(node)
34          self._check_log_methods(node)
35 
36      def _check_convenience_methods(self, node):
diff --git a/test/input/func_bug113231.py b/test/input/func_bug113231.py
@@ -0,0 +1,24 @@
37 +# pylint: disable=E1101
38 +# pylint: disable=C0103
39 +# pylint: disable=R0903
40 +"""test bugfix for #113231 in logging checker
41 +"""
42 +
43 +__revision__ = ''
44 +
45 +# Muck up the names in an effort to confuse...
46 +import logging as renamed_logging
47 +
48 +class Logger(object):
49 +    """Fake logger"""
50 +    pass
51 +
52 +logger = renamed_logging.getLogger(__name__)
53 +fake_logger = Logger()
54 +
55 +# Statements that should be flagged:
56 +renamed_logging.warn('%s, %s' % (4, 5))
57 +logger.warn('%s' % 5)
58 +
59 +# Statements that should not be flagged:
60 +fake_logger.warn('%s' % 5)
diff --git a/test/messages/func_bug113231.txt b/test/messages/func_bug113231.txt
@@ -0,0 +1,2 @@
61 +W: 20: Specify string format arguments as logging function parameters
62 +W: 21: Specify string format arguments as logging function parameters