Code Monkey home page Code Monkey logo

vulture's Introduction

Vulture - Find dead code

CI:Test Codecov Badge

Vulture finds unused code in Python programs. This is useful for cleaning up and finding errors in large code bases. If you run Vulture on both your library and test suite you can find untested code.

Due to Python's dynamic nature, static code analyzers like Vulture are likely to miss some dead code. Also, code that is only called implicitly may be reported as unused. Nonetheless, Vulture can be a very helpful tool for higher code quality.

Features

  • fast: uses static code analysis
  • tested: tests itself and has complete test coverage
  • complements pyflakes and has the same output syntax
  • sorts unused classes and functions by size with --sort-by-size

Installation

$ pip install vulture

Usage

$ vulture myscript.py  # or
$ python3 -m vulture myscript.py
$ vulture myscript.py mypackage/
$ vulture myscript.py --min-confidence 100  # Only report 100% dead code.

The provided arguments may be Python files or directories. For each directory Vulture analyzes all contained *.py files.

After you have found and deleted dead code, run Vulture again, because it may discover more dead code.

Types of unused code

In addition to finding unused functions, classes, etc., Vulture can detect unreachable code. Each chunk of dead code is assigned a confidence value between 60% and 100%, where a value of 100% signals that it is certain that the code won't be executed. Values below 100% are very rough estimates (based on the type of code chunk) for how likely it is that the code is unused.

Code type Confidence value
function/method/class argument, unreachable code 100%
import 90%
attribute, class, function, method, property, variable 60%

You can use the --min-confidence flag to set the minimum confidence for code to be reported as unused. Use --min-confidence 100 to only report code that is guaranteed to be unused within the analyzed files.

Handling false positives

When Vulture incorrectly reports chunks of code as unused, you have several options for suppressing the false positives. If fixing your false positives could benefit other users as well, please file an issue report.

Whitelists

The recommended option is to add used code that is reported as unused to a Python module and add it to the list of scanned paths. To obtain such a whitelist automatically, pass --make-whitelist to Vulture:

$ vulture mydir --make-whitelist > whitelist.py
$ vulture mydir whitelist.py

Note that the resulting whitelist.py file will contain valid Python syntax, but for Python to be able to run it, you will usually have to make some modifications.

We collect whitelists for common Python modules and packages in vulture/whitelists/ (pull requests are welcome).

Ignoring files

If you want to ignore a whole file or directory, use the --exclude parameter (e.g., --exclude "*settings.py,*/docs/*.py,*/test_*.py,*/.venv/*.py"). The exclude patterns are matched against absolute paths.

Flake8 noqa comments

For compatibility with flake8, Vulture supports the F401 and F841 error codes for ignoring unused imports (# noqa: F401) and unused local variables (# noqa: F841). However, we recommend using whitelists instead of noqa comments, since noqa comments add visual noise to the code and make it harder to read.

Ignoring names

You can use --ignore-names foo*,ba[rz] to let Vulture ignore all names starting with foo and the names bar and baz. Additionally, the --ignore-decorators option can be used to ignore the names of functions decorated with the given decorator (but not their arguments or function body). This is helpful for example in Flask projects, where you can use --ignore-decorators "@app.route" to ignore all function names with the @app.route decorator. Note that Vulture simplifies decorators it cannot parse: @foo.bar(x, y) becomes "@foo.bar" and @foo.bar(x, y).baz becomes "@" internally.

We recommend using whitelists instead of --ignore-names or --ignore-decorators whenever possible, since whitelists are automatically checked for syntactic correctness when passed to Vulture and often you can even pass them to your Python interpreter and let it check that all whitelisted code actually still exists in your project.

Marking unused variables

There are situations where you can't just remove unused variables, e.g., in function signatures. The recommended solution is to use the del keyword as described in the PyLint manual and on StackOverflow:

def foo(x, y):
    del y
    return x + 3

Vulture will also ignore all variables that start with an underscore, so you can use _x, y = get_pos() to mark unused tuple assignments or function arguments, e.g., def foo(x, _y).

Minimum confidence

Raise the minimum confidence value with the --min-confidence flag.

Unreachable code

If Vulture complains about code like if False:, you can use a Boolean flag debug = False and write if debug: instead. This makes the code more readable and silences Vulture.

Forward references for type annotations

See #216. For example, instead of def foo(arg: "Sequence"): ..., we recommend using

from __future__ import annotations

def foo(arg: Sequence):
    ...

Configuration

You can also store command line arguments in pyproject.toml under the tool.vulture section. Simply remove leading dashes and replace all remaining dashes with underscores.

Options given on the command line have precedence over options in pyproject.toml.

Example Config:

[tool.vulture]
exclude = ["*file*.py", "dir/"]
ignore_decorators = ["@app.route", "@require_*"]
ignore_names = ["visit_*", "do_*"]
make_whitelist = true
min_confidence = 80
paths = ["myscript.py", "mydir", "whitelist.py"]
sort_by_size = true
verbose = true

Vulture will automatically look for a pyproject.toml in the current working directory.

To use a pyproject.toml in another directory, you can use the --config path/to/pyproject.toml flag.

Version control integration

You can use a pre-commit hook to run Vulture before each commit. For this, install pre-commit and add the following to the .pre-commit-config.yaml file in your repository:

repos:
  - repo: https://github.com/jendrikseipp/vulture
    rev: 'v2.3'  # or any later Vulture version
    hooks:
      - id: vulture

Then run pre-commit install. Finally, create a pyproject.toml file in your repository and specify all files that Vulture should check under [tool.vulture] --> paths (see above).

How does it work?

Vulture uses the ast module to build abstract syntax trees for all given files. While traversing all syntax trees it records the names of defined and used objects. Afterwards, it reports the objects which have been defined, but not used. This analysis ignores scopes and only takes object names into account.

Vulture also detects unreachable code by looking for code after return, break, continue and raise statements, and by searching for unsatisfiable if- and while-conditions.

Sort by size

When using the --sort-by-size option, Vulture sorts unused code by its number of lines. This helps developers prioritize where to look for dead code first.

Examples

Consider the following Python script (dead_code.py):

import os

class Greeter:
    def greet(self):
        print("Hi")

def hello_world():
    message = "Hello, world!"
    greeter = Greeter()
    func_name = "greet"
    greet_func = getattr(greeter, func_name)
    greet_func()

if __name__ == "__main__":
    hello_world()

Calling :

$ vulture dead_code.py

results in the following output:

dead_code.py:1: unused import 'os' (90% confidence)
dead_code.py:4: unused function 'greet' (60% confidence)
dead_code.py:8: unused variable 'message' (60% confidence)

Vulture correctly reports os and message as unused but it fails to detect that greet is actually used. The recommended method to deal with false positives like this is to create a whitelist Python file.

Preparing whitelists

In a whitelist we simulate the usage of variables, attributes, etc. For the program above, a whitelist could look as follows:

# whitelist_dead_code.py
from dead_code import Greeter
Greeter.greet

Alternatively, you can pass --make-whitelist to Vulture and obtain an automatically generated whitelist.

Passing both the original program and the whitelist to Vulture

$ vulture dead_code.py whitelist_dead_code.py

makes Vulture ignore the greet method:

dead_code.py:1: unused import 'os' (90% confidence)
dead_code.py:8: unused variable 'message' (60% confidence)

Exit codes

Exit code Description
0 No dead code found
1 Invalid input (file missing, syntax error, wrong encoding)
2 Invalid command line arguments
3 Dead code found

Similar programs

  • pyflakes finds unused imports and unused local variables (in addition to many other programmatic errors).
  • coverage finds unused code more reliably than Vulture, but requires all branches of the code to actually be run.
  • uncalled finds dead code by using the abstract syntax tree (like Vulture), regular expressions, or both.
  • dead finds dead code by using the abstract syntax tree (like Vulture).

Participate

Please visit https://github.com/jendrikseipp/vulture to report any issues or to make pull requests.

vulture's People

Contributors

agathiyanb avatar andrewhalle avatar bassdread avatar bcbnz avatar bje- avatar chayim avatar eltoder avatar exhuma avatar fcostin avatar glenrobertson avatar hugovk avatar jackric avatar jbylund avatar jendrikseipp avatar jogo avatar johnyf avatar ju-sh avatar kianmeng avatar kreathon avatar kx-chen avatar maxrake avatar milanbalazs avatar mssalvatore avatar nalinbhardwaj avatar neutrinoceros avatar rj722 avatar sacsar avatar the-compiler avatar tqa236 avatar whosayn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vulture's Issues

Mistake in calling function

When you assign a function to a variable you don't use the () but simply the name of the function.
In your case given def x(): ..., and variable silly_var you would do something like this:
silly_var = x
and then you can call the function either with
x()
or
silly_var()

In test_scavenging.py
func is written instead of func().

Augment output with size of unused functions/variables

When Vulture finds lots of unused variables and functions in a codebase, it would be useful to show the size (as lines/AST contents/etc) of each entity. This allows a developer to prioritize his purging work, i.e. pick the juiciest low hanging fruit first.

dead code calling other dead code

Originally reported by: Anonymous


if a function calls a function and there both dead because no one is calling the first function, only the first one will be called dead by the tool because that dead function is calling it.
how about adding recursive mode after a first scan all the presumed dead function will be marked as an comment and the function will run again until no dead code will find.
after that all the files will need to be revert back of course.
I've attached an example in witch only func2 is detected as dead although other function are dead as well.


Django awareness

Originally reported by: Daniel Watkins (Bitbucket: Odd_Bloke, GitHub: Unknown)


Django has a few metaclass things that Vulture doesn't pick up on (Meta on models and fields on models and form to name the two most obvious). It'd be good if Vulture could be told to ignore unused variables that look Django-ish (perhaps with a --django CLI switch).


API

Originally reported by: Lasse Schuirmann (Bitbucket: sils1297, GitHub: sils1297)


Would be nice to have a way to use vulture programmatically, like:

from vulture import find_unused_code

find_unused_code(
    files={'test_1': 'def test(): pass', 'test_2': 'def test2: pass\nfrom test_1 import test\ntest()'}
    )

We use vulture in coala (coala.io) and that'd make things way more efficient etc. (in memory file passing, we have them already read e.g.)


Ignore methods/attributes with a certain property (cherrypy exposed)

Originally reported by: Magnus Carlsson (Bitbucket: grimmySwe, GitHub: grimmySwe)


We use cherrypy as a web framework and there you define a lot of methods as handlers for the framework, they are all marked with the exposed property.

It would be nice if you could somehow tell vulture that it should ignore all things with the exposed property.

The code looks like this:

#!python

class Page():
    def handler(self):
         return data
    handler.exposed = True

or this:

#!python

class Page():
    @cherrypy.expose
    def handler(self):
         return data

Running vulture will report handler. (and exposed... but thats only one line to whitelist)


Use stdlib whitelist by default

Whitelists are a great way to tackle false positives, but we have to explicitly mention the whitelist fie every time we execute vulture, so should vulture use whitelist by default?

Make vulture available as a library

Reference: coala vulture project

IMO, what we implicate when we say that make vulture available as a library is to perhaps extend the functionality of vulture to be directly incorporated in code, rather than just as a command line feature.
But we already have vulture.scan() for that, so I am a little confused on what else do we need here?

Better usage information

Originally reported by: Drew Ayling (Bitbucket: drewayling, GitHub: Unknown)


The usage is really confusing and doesn't really provide any insight as to "how" it executes or what PATH is. Is path a file? Path to a module? Path to a package

What is the difference in these?

  $ vulture

  $ vulture .

  $ vulture script.py

  $ vulture package/

What if I want to analyze across multiple modules or packages?

I can inspect your code and see that scavenge is called with paths, which only works down from the path provided. Some better explanation and usages would be really helpful for new users.


Variable with same name in different classes only gets reported once

Originally reported by: Florian Bruhin (Bitbucket: The-Compiler, GitHub: The-Compiler)


With this source file:

class Foo:

    unused = 'asfa'


class Bar:

    unused = 'asfa'


Foo()
Bar()

vulture only complains about the first occurence:

test.py:3: Unused variable 'unused'

If I do Foo().unused instead of Foo(), vulture doesn't complain at all, despite Bar.unused still being unused.


How to whitelist vars in context manager's __exit__() method?

I've just started to use vulture and already found it helpful.

However, I often have context managers where all I want to do is call a cleanup function and let any exception continue to be raised, e.g.:

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.close()

But I can't work out how to whitelist exc_type, exc_val, exc_tb. Is it possible?

BTW I think the docs for whitelist.py could be a bit more explicit. Here's one I'm using which I think shows how to do it:

# whitelist.py
from Parser import humanTime, Reader, Chunk, lzw, Normalize
unused = (humanTime, Reader, lzw.readbytes, lzw.writebytes,
          Chunk.height, Normalize.isspace)
unused = len(unused)

Package vulture

We need to provide vulture as a package in order to ship additional package data like whitelists, etc.

Directory structure:

vulture/
    __init__.py (contains __version__)
    core.py (with the contents from old vulture.py)

Refer: #50 (comment)

Handle syntactically invalid files

Originally reported by: Wilfred Hughes (Bitbucket: Wilfred, GitHub: Wilfred)


I want to run vulture inside Emacs, so it spots issues as I type. However, vulture assumes that the current file is syntactically valid, and shows a traceback if not.

Given the code:

def foo(

I get the following behaviour:

$ vulture /tmp/broken.py
Traceback (most recent call last):
  File "/users/is/whughes/pyenvs/research/bin/vulture", line 9, in <module>
    load_entry_point('vulture==0.9', 'console_scripts', 'vulture')()
  File "/users/is/whughes/src/vulture/vulture.py", line 317, in main
    vulture.scavenge(args)
  File "/users/is/whughes/src/vulture/vulture.py", line 136, in scavenge
    self.scan(module_string, filename=module)
  File "/users/is/whughes/src/vulture/vulture.py", line 102, in scan
    node = ast.parse(node_string, filename=self.filename)
  File "/opt/ahl/releases/python/2.7.3/lib64/python2.7/ast.py", line 37, in parse
    return compile(source, filename, mode, PyCF_ONLY_AST)
  File "/tmp/broken.py", line 1
    def foo(
           ^
SyntaxError: unexpected EOF while parsing
$ pyflakes /tmp/broken.py
/tmp/broken.py:1:9: unexpected EOF while parsing
def foo(
        ^

I think vulture should do the same thing as pyflakes here, and just show an error. This means it's always safe to run vulture on arbitrary python code and expect its output to be in the usual format.


unused for loop variable

Hi, I really like this library.

I'm have been getting unused messages about the variable defined by a for loop which is just a place holder.

Ex

for repeat in range(10):
    do something that doesn't use repeat

Vulture doesn't detect unused function

Originally reported by: Anonymous


Am I doing something wrong?

#!python

lasse@lssteady ~/prog/coala-bears (git)-[sils/reqa] % cat test.py 
def teest(a):
    return a+2


def test_unused(a):
    return a+2
lasse@lssteady ~/prog/coala-bears (git)-[sils/reqa] % cat test2.py 
from test import teest, test_unused

teest()
lasse@lssteady ~/prog/coala-bears (git)-[sils/reqa] % vulture test.py test2.py 
lasse@lssteady ~/prog/coala-bears (git)-[sils/reqa] % vulture test.py 
test.py:1: Unused function 'teest'
1 lasse@lssteady ~/prog/coala-bears (git)-[sils/reqa] % vulture test2.py
lasse@lssteady ~/prog/coala-bears (git)-[sils/reqa] % 

why not move to github?

Originally reported by: Ioannis Filippidis (Bitbucket: johnyf, GitHub: johnyf)


It certainly has a better interface, and more interaction with other developers is expected. Also, cross-references between repository issues, watching etc. Fast-export/import should work quite well (it has worked for me well in the past). The number of issues listed in this issue tracker is still relatively small, so it would be beneficial to move early on, before there are many open issues (potentially).


Mark code as "Allowed"

Originally reported by: Anonymous


I am looking into using vulture for my code base and one of the first thing I ran into was how to accept some errors. So I don't have to see them in future runs.

I think I will end up with some kind of wrapper around vulture checking output against an list of allowed strings.

But if you have a better solution please include it in your program!


Handle syntax errors gracefully

Originally reported by: Steven Myint (Bitbucket: myint, GitHub: myint)


vulture crashes when run on Python's standard library.

$ vulture /opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/lib2to3/
Traceback (most recent call last):
  File "/Users/myint/Library/Python/3.3/bin/vulture", line 44, in <module>
    vulture.scavenge(args)
  File "/Users/myint/Library/Python/3.3/lib/python/site-packages/wake.py", line 96, in scavenge
    self.scan(module_string)
  File "/Users/myint/Library/Python/3.3/lib/python/site-packages/wake.py", line 67, in scan
    node = ast.parse(node_string)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/ast.py", line 35, in parse
    return compile(source, filename, mode, PyCF_ONLY_AST)
  File "<unknown>", line 1
    # coding: utf-8
      ^
SyntaxError: invalid character in identifier

Report unset attributes?

Originally reported by: Anonymous


Maybe I've already asked this. It would be kind of nice if you
could identify referenced but unset attributes (maybe using a
command line flag or config file variable). That's another common
bug. (It's rare a class to not set one of its own attributes, relying
instead on some external object to do its initialization.)


use vulture to automatically remove dead code?

Originally reported by: Jendrik Seipp (Bitbucket: jendrikseipp, GitHub: jendrikseipp)


I'm adding this issue since the topic came up in a discussion around GSoC proposals for www.coala.io with @sils1297. The idea was to write a program that uses vullture to find and remove dead code.

After thinking some more about this, I think that the benefits of such a program are very small. For a program that changes code to be useful, most of the changes it proposes have to make sense. This is the case, e.g., for tools like autopep8. However, vulture (due to Python's dynamic nature) produces too many false positives. Even if it detects dead code, the underlying issue is not that code should be removed, but that e.g. a variable name is misspelled and therefore seems to be unused. Vulture is useful for hinting at possible programming errors, but I think almost all of them will have to be double-checked by the programmer.


Overriden methods of C/C++ extensions

Originally reported by: Florian Bruhin (Bitbucket: The-Compiler, GitHub: The-Compiler)


When subclassing a method of a class defined in a C/C++ extension, such as this example using the PyQt GUI framework:

from PyQt5.QtCore import QSize
from PyQt5.QtWidgets import QLineEdit, QApplication


class LineEdit(QLineEdit):

    def sizeHint(self):
        return QSize(128, 128)

app = QApplication([])
le = LineEdit()
le.show()
app.exec_()

vulture doesn't detect that sizeHint is called via C++:

foo.py:7: Unused function 'sizeHint'

Maybe if a class inherits from a non-Python class, and an existing method is overridden, it should always be considered used?


Implement confidence values

It would be nice if vulture reports a confidence value associated with every result.

Strategy for calculating confidence values:

  • imports are reported with 100% confidence
  • Anything we are not sure about should be reported with 50% confidence
  • * imports should with 0 % confidence
Construct Confidence
import 100%
from foo import * 0%
variable 50%
function 50%
class 50%

Adding some way to deal with dynamicly called functions

Originally reported by: Florian Bruhin (Bitbucket: The-Compiler, GitHub: The-Compiler)


First of all: Thanks for vulture! I just discovered it today, and found some points which makes it hard for me to use currently - I'll open two or three issues for those :)

The first thing I noticed is that I have some dynamic functions which (naturally) vulture can't detect. These are all decorated with @cmdutils.register, get registered into some dict in that decorator, and then get called dynamically (they are exposed as commands to the user).

Now I was thinking about possible solutions for that. What came to mind so far are these possibilities:

  • Having some way to whitelist a decorator, and everything decorated by that is considered "used".
  • Always marking a function which is decorated as used (maybe only if the decorator returns the unmodified function? That might be hard though...).
  • Having some more intelligent whitelist file (or argument), which can execute python code to generate a list of (fully qualified) names to be ignored.

What are your thoughts about this?


Doesn't search for scripts without .py extension

Originally reported by: Anonymous


Vulture doesn't search for scripts without .py extension, for example:

estevo@paz:~/analytics/backend$ file bin/AnaDaemon
bin/AnaDaemon: Python script, ASCII text executable

estevo@paz:~/analytics/backend$ vulture . | grep get_email_default_consultants
ana/metadata/api.py:326: Unused function 'get_email_default_consultants'

estevo@paz:~/analytics/backend$ grep get_email_default_consultants bin/*
bin/AnaDataCollector: for email in meta_api.get_email_default_consultants():


Vulture doesn't handle mixins?

If I have a mixin with some base code that is going to be used by a number of classes


MyMixin(object):

  def check_status(self):
      return ...

MyClass(MyMixin):
  ....

Vulture seems to complain that check_status is an unused function

edit: maybe this is because check_status is called by another mixin


# some.third.party
MyOtherMixin(object):

  def check_object(self):
    status = self.check_status()
    ...

# local.py
from some.third.party import MyOtherMixin

MyClass(MyMixin, MyOtherMixin):
  ...

Provide a way of disabling unused attribute checks

Originally reported by: Wilfred Hughes (Bitbucket: Wilfred, GitHub: Wilfred)


I'm seeing quite a high false positive rate on unused attribute checks in vulture. For example, I work with pandas a lot. Here's me explicitly assigning to an attribute with pandas:

#!python
import pandas as pd

def some_function_returns_a_dataframe():
    return pd.DataFrame({'a':[1, 2], 'b': [10, 20]})

def get_dataframe_and_rename_columns():
    df = some_function_returns_a_dataframe()
    df.columns = ['x', 'y']
    return df

Vulture complains "Unused attribute 'columns'" for this code. Could you provide a way of disabling the unused attribute check entirely?


unused functions' parameters and unused variables having same names are not reported.

For example. running vulture on the following file:

first_name = "Rahul"
sur_name = "Jha"

def say_hello(first_name, sur_name):
	# first_name and sur_name are not reported
	pass

we would have following results:

dead.py:1: Unused variable 'first_name'
dead.py:2: Unused variable 'sur_name'
dead.py:4: Unused function 'say_hello'

It should also report that first_name, sur_name in line 4 are not being used as in this case:

first_name = "Rahul"
sur_name = "Jha"

def say_hello(a, b):
	# first_name and sur_name are not reported by vulture
	pass

which would produce:

dead2.py:1: Unused variable 'first_name'
dead2.py:2: Unused variable 'sur_name'
dead2.py:4: Unused function 'say_hello'
dead2.py:4: Unused variable 'a'
dead2.py:4: Unused variable 'b'

Is this a bug?

Implement --min-confidence flag

Input of the flag should be the minimum confidence value (CV)) - results having a CV lower than this should not be reported.

Usage:

vulture file.py --min-confidence 70

should only show the results which have a CV >= 70%.

Add test for whitelist.py

While writing a test case for whitelist_python.py, I realised that we can potentially write a test case that can check whether or not whitelisting works or not and would it give an error if whitelist.py is not supplied!

Is it feasible to do so @jendrikseipp?

Globals across modules marked as unused

Originally reported by: Florian Bruhin (Bitbucket: The-Compiler, GitHub: The-Compiler)


When I have a foo.py:

import bar

bar.attr = True
bar.blub()

and a bar.py:

attr = False

def blub():
    if attr:
        print("Hey!")

vulture says:

$ vulture foo.py bar.py
foo.py:3: Unused attribute 'attr'

verbose output:

Scanning: /home/florian/proj/qutebrowser/git/foo.py
1 Import(names=[alias(name='bar', asname=None)]) import bar
3 Assign(targets=[Attribute(value=Name(id='bar', ctx=Load()), attr='attr', ctx=Store())], value=NameConstant(value=True)) bar.attr = True
3 Attribute(value=Name(id='bar', ctx=Load()), attr='attr', ctx=Store()) bar.attr = True
defined_attrs <- attr
3 Name(id='bar', ctx=Load()) bar.attr = True
used_vars <- bar
4 Attribute(value=Name(id='bar', ctx=Load()), attr='blub', ctx=Load()) bar.blub()
used_attrs <- blub
4 Name(id='bar', ctx=Load()) bar.blub()
used_vars <- bar
Scanning: /home/florian/proj/qutebrowser/git/bar.py
1 Assign(targets=[Name(id='attr', ctx=Store())], value=NameConstant(value=False)) attr = False
1 Name(id='attr', ctx=Store()) attr = False
defined_vars <- attr
3 FunctionDef(name='blub', args=arguments(args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[If(test=Name(id='attr', ctx=Load()), body=[Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Str(s='Hey!')], keywords=[], starargs=None, kwargs=None))], orelse=[])], decorator_list=[], returns=None) def blub():
4 Name(id='attr', ctx=Load())     if attr:
used_vars <- attr
5 Name(id='print', ctx=Load())         print("Hey!")
used_vars <- print
5 Str(s='Hey!')         print("Hey!")
foo.py:3: Unused attribute 'attr'

I agree it's not really good style, but still, the attribute definitely is used.


Unused attributes on arguments

Originally reported by: Florian Bruhin (Bitbucket: The-Compiler, GitHub: The-Compiler)


I'm back on trying to use vulture with my PyQt project 😉

Sometimes, there are places where Qt passes an argument to a (virtual) function and expects some attributes to be set - something like this:

class CompletionItemDelegate(QStyledItemDelegate):

    def paint(self, ...):
        # ...
        rect = QRectF(...)
        clip = QRectF(0, 0, rect.width(), rect.height())
        ctx = QAbstractTextDocumentLayout.PaintContext()
        ctx.palette.setColor(QPalette.Text, self._painter.pen().color())
        if clip.isValid():
            self._painter.setClipRect(clip)
            ctx.clip = clip
        self._doc.documentLayout().draw(self._painter, ctx)  # implemented in C++

Here, vulture will say ctx.clip is unused:

qutebrowser/completion/completiondelegate.py:164: Unused attribute 'clip'

(real code here)

How should I whitelist this from a whitelist.py file? I don't have a way to access ctx from there at all. I could do:

if False:  # pragma: no cover
    ctx.clip  # pylint: disable=pointless-statement

in my code, but that strikes me as ugly... I still think having a # vulture: whitelist comment would be useful.


There is no requirements file

IMHO we should have two files:

requirements.txt:

pbr==3.0.1
six==1.10.0
stevedore==1.23.0
virtualenv==15.1.0
vulture==0.14

test-requirements.txt:

pluggy==0.4.0
py==1.4.34
tox==2.7.0

syntax based errors when running vulture installed through pypi

I installed installed through pypi for python2.7.12 (in an isolated virtualenv).
Then ran:

vulture localstack --exclude=localstack/.venv/

It gave the following output:

localstack/localstack/dashboard/infra.py:126: invalid syntax at "except Exception, e:"
localstack/localstack/mock/apis/firehose_api.py:65: invalid syntax at "except Exception, e:"
localstack/localstack/mock/apis/lambda_api.py:97: invalid syntax at "except Exception, e:"
localstack/localstack/mock/generic_proxy.py:71: invalid syntax at "except Exception, e:"
localstack/localstack/mock/infra.py:239: invalid syntax at "except Exception, e:"
localstack/localstack/utils/aws/aws_models.py:43: invalid syntax at "except Exception, e:"
localstack/localstack/utils/aws/aws_stack.py:87: invalid syntax at "except Exception, e:"
localstack/localstack/utils/common.py:43: invalid syntax at "except Exception, e:"
localstack/localstack/utils/kinesis/kinesis_connector.py:97: invalid syntax at "except Exception, e:"
localstack/localstack/utils/kinesis/kinesis_util.py:31: invalid syntax at "except Exception, e:"
localstack/setup.py:40: Missing parentheses in call to 'print' at "print e.output"
localstack/tests/test_integration.py:180: invalid syntax at "except KeyboardInterrupt, e:"
localstack/tests/test_kinesis_errors.py:43: invalid syntax at "except KeyboardInterrupt, e:"
localstack/localstack/constants.py:10: Unused variable 'REGION_LOCAL'
localstack/localstack/constants.py:13: Unused variable 'ENV_DEV'
localstack/localstack/constants.py:26: Unused variable 'DEFAULT_PORT_REDSHIFT'
localstack/localstack/constants.py:28: Unused variable 'DEFAULT_PORT_APIGATEWAY_BACKEND'
localstack/localstack/constants.py:29: Unused variable 'DEFAULT_PORT_KINESIS_BACKEND'
localstack/localstack/constants.py:30: Unused variable 'DEFAULT_PORT_DYNAMODB_BACKEND'
localstack/localstack/constants.py:31: Unused variable 'DEFAULT_PORT_SNS_BACKEND'
localstack/localstack/constants.py:47: Unused variable 'BIND_HOST'
localstack/localstack/constants.py:85: Unused variable 'APPLICATION_AMZ_JSON_1_0'
localstack/localstack/constants.py:86: Unused variable 'APPLICATION_AMZ_JSON_1_1'
localstack/localstack/constants.py:90: Unused variable 'LAMBDA_TEST_ROLE'
localstack/localstack/constants.py:91: Unused variable 'LAMBDA_MAIN_SCRIPT_NAME'
localstack/localstack/constants.py:94: Unused variable 'ELASTICSEARCH_JAR_URL'
localstack/localstack/dashboard/api.py:14: Unused function 'spec'
localstack/localstack/dashboard/api.py:64: Unused function 'hello'
localstack/localstack/dashboard/api.py:69: Unused function 'send_static'
localstack/localstack/mock/apis/dynamodbstreams_api.py:5: Unused import 'uuid'
localstack/localstack/mock/apis/dynamodbstreams_api.py:8: Unused import '__init__'
localstack/localstack/mock/apis/dynamodbstreams_api.py:28: Unused function 'post_request'
localstack/localstack/mock/proxy/apigateway_listener.py:7: Unused function 'update_apigateway'
localstack/localstack/mock/proxy/dynamodb_listener.py:11: Unused function 'update_dynamodb'
localstack/localstack/mock/proxy/dynamodb_listener.py:23: Unused variable 'response_data'
localstack/localstack/mock/proxy/kinesis_listener.py:8: Unused function 'update_kinesis'
localstack/localstack/mock/proxy/kinesis_listener.py:39: Unused attribute 'status_code'
localstack/localstack/mock/proxy/kinesis_listener.py:46: Unused attribute '_content'
localstack/localstack/mock/proxy/sns_listener.py:13: Unused function 'update_sns'
localstack/localstack/utils/kinesis/kclipy_helper.py:6: Unused import 'run'
localstack/localstack/utils/kinesis/kclipy_helper.py:8: Unused import 'argparse'
localstack/localstack/utils/kinesis/kclipy_helper.py:10: Unused import 'samples'
localstack/localstack/utils/kinesis/kclipy_helper.py:11: Unused import 'traceback'
localstack/localstack/utils/kinesis/kclipy_helper.py:61: Unused function 'get_kcl_app_command'
localstack/localstack/utils/kinesis/kclipy_helper.py:90: Unused function 'create_config_file'
localstack/tests/lambdas/lambda_integration.py:12: Unused function '_deserialize_n'
localstack/tests/lambdas/lambda_integration.py:15: Unused function '_deserialize_b'
localstack/tests/lambdas/lambda_integration.py:19: Unused function 'handler'
localstack/tests/test_iam_credentials.py:4: Unused import 'time'

But, since it had based error messages , I tried the same with vulture for python3, still the same results. 😕
Trying a command:

python /path/to/vulture.py localstack --exclude=localstack/.venv/

made it work!
What can be possible reasons?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.