Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detect unused functions and classes in closures #485

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
fix
adamchainz committed Nov 16, 2019

Unverified

This user has not yet uploaded their public signing key.
commit e0ba211ab61001a14977c28b275d2be8c5eeac81
18 changes: 11 additions & 7 deletions pyflakes/checker.py
Original file line number Diff line number Diff line change
@@ -568,16 +568,15 @@ def __init__(self):
self.returnValue = None # First non-empty return
self.isGenerator = False # Detect a generator

def unusedAssignments(self):
def unusedBindings(self):
"""
Return a generator for the assignments which have not been used.
"""
for name, binding in self.items():
if (not binding.used and
name != '_' and # see issue #202
name not in self.globals and
not self.usesLocals and
isinstance(binding, Assignment)):
not self.usesLocals):
yield name, binding


@@ -1839,13 +1838,18 @@ def runFunction():

self.handleChildren(node, omit=['decorator_list', 'returns'])

def checkUnusedAssignments():
def checkUnusedBindings():
"""
Check to see if any assignments have not been used.
"""
for name, binding in self.scope.unusedAssignments():
self.report(messages.UnusedVariable, binding.source, name)
self.deferAssignment(checkUnusedAssignments)
for name, binding in self.scope.unusedBindings():
if isinstance(binding, Assignment):
self.report(messages.UnusedVariable, binding.source, name)
elif isinstance(binding, ClassDefinition):
self.report(messages.UnusedClass, binding.source, name)
elif isinstance(binding, FunctionDefinition):
self.report(messages.UnusedFunction, binding.source, name)
self.deferAssignment(checkUnusedBindings)

if PY2:
def checkReturnWithArgumentInsideGenerator():
22 changes: 22 additions & 0 deletions pyflakes/messages.py
Original file line number Diff line number Diff line change
@@ -168,6 +168,28 @@ def __init__(self, filename, loc, names):
self.message_args = (names,)


class UnusedFunction(Message):
"""
Indicates that a function has been defined but not actually used.
"""
message = 'local function %r is defined but never used'

def __init__(self, filename, loc, names):
Message.__init__(self, filename, loc)
self.message_args = (names,)


class UnusedClass(Message):
"""
Indicates that a class has been defined but not actually used.
"""
message = 'local class %r is defined but never used'

def __init__(self, filename, loc, names):
Message.__init__(self, filename, loc)
self.message_args = (names,)


class ReturnWithArgsInsideGenerator(Message):
"""
Indicates a return statement with arguments inside a generator.