[code-quality] Spurious unused variable messages

Claudiu Popa pcmanticore at gmail.com
Wed Jun 10 23:28:45 CEST 2015


Hi,

On Thu, Jun 11, 2015 at 12:02 AM, Skip Montanaro
<skip.montanaro at gmail.com> wrote:
>
> As I stated, I think that string literal formatting will be the most
> common form.  The token stream around that should look something like
>
>     STRING-LITERAL DOT "format"
>
> (however that's spelled).  What I'm initially interested in knowing is
> what visit_* method(s) would be involved in processing such a
> construct.  I really don't have any idea where to begin.  I think it's
> going to involve astroid, but I haven't found any documentation so
> far.


Unfortunately, we don't have a very good documentation, so most of the time,
you can find more about something by reading the code or asking on IRC, rather
than trying to find it in the documentation. That being said, regarding
your use case, I don't think you actually need to implement any
visit traversal function.

Here's a suggestion: In checkers.variables.leave_function, when
determined that there are unused variables, call a function which
gathers all the string formatting calls from the function's scope,
by doing something like this:

   for callfunc in node.nodes_of_class(astroid.CallFunc):
       # Infer it
       func = utils.safe_infer(callfunc.func)
      # Check if it is a string
      if (isinstance(func, astroid.BoundMethod)
              and isinstance(func.bound, astroid.Instance)
              and func.bound.name in ('str', 'unicode', 'bytes')):
          if func.name == 'format':
                # start parsing the string and gather the used variables.

Having the list of used variables from the parsed strings, pop them out of
the container of unused variables (not_consumed) and that should be it.
Of course, you should check that the string formatting uses **locals.

>
> Is it possible to build an add-on for pylint which I could mess around
> with?  If so, and if I can learn how the basic token traversal works,
> then I think I could mess around without tickling core pylint.

Well, you could start playing with astroid first. Start by building an
AST module
using astroid.AstroidBuilder:

  from astroid.builder import AstroidBuilder
  ast = AstroidBuilder().string_build(code_string)

The traversal just calls visit_<node_name> and leave_<node_name>
(see pylint.utils.PyLintASTWalker).

>
>> Apropos of nothing, the empty {} only works on 2.7 and beyond.  2.6
>> didn't support that. If you're going for 2.6 compat, you'll want to
>> avoid that.
>
> Not an issue.  I only mentioned 2.6 because that's when the
> string.Formatter class appeared.  In my own environment, 2.7 is the
> standard.

Pylint 1.4+ doesn't support Python 2.6 anymore.

Hope this info helps.


/Claudiu


More information about the code-quality mailing list