Python: Autoformat statements

This commit is contained in:
Rasmus Wriedt Larsen
2020-02-06 14:48:31 +01:00
parent c94582a1c0
commit 381668871d
25 changed files with 249 additions and 217 deletions

View File

@@ -26,7 +26,5 @@ where
value = test.(NameConstant).toString()
) and
/* Exclude asserts appearing at the end of a chain of `elif`s */
not exists(If i |
i.getElif().getAnOrelse() = a
)
not exists(If i | i.getElif().getAnOrelse() = a)
select a, "Assert of literal constant " + value + "."

View File

@@ -14,11 +14,14 @@
import python
from Assert a, string b, string non
where a.getTest() instanceof Tuple and
(if exists(((Tuple)a.getTest()).getAnElt()) then
(b = "True" and non = "non-")
else
(b = "False" and non = "")
)
where
a.getTest() instanceof Tuple and
(
if exists(a.getTest().(Tuple).getAnElt())
then (
b = "True" and non = "non-"
) else (
b = "False" and non = ""
)
)
select a, "Assertion of " + non + "empty tuple is always " + b + "."

View File

@@ -15,13 +15,13 @@
import python
from Stmt s, string kind
where
s instanceof Return and kind = "return" and exists(Try t | t.getFinalbody().contains(s))
or
s instanceof Break and kind = "break" and
exists(Try t | t.getFinalbody().contains(s) |
not exists(For loop | loop.contains(s) and t.getFinalbody().contains(loop))
and
not exists(While loop | loop.contains(s) and t.getFinalbody().contains(loop))
)
where
s instanceof Return and kind = "return" and exists(Try t | t.getFinalbody().contains(s))
or
s instanceof Break and
kind = "break" and
exists(Try t | t.getFinalbody().contains(s) |
not exists(For loop | loop.contains(s) and t.getFinalbody().contains(loop)) and
not exists(While loop | loop.contains(s) and t.getFinalbody().contains(loop))
)
select s, "'" + kind + "' in a finally block will swallow any exceptions raised."

View File

@@ -14,19 +14,22 @@
import python
from Expr e, Location l, string kind, string what
where e.isParenthesized() and
not e instanceof Tuple and
(
exists(If i | i.getTest() = e) and kind = "if" and what = "condition"
or
exists(While w | w.getTest() = e) and kind = "while" and what = "condition"
or
exists(Return r | r.getValue() = e) and kind = "return" and what = "value"
or
exists(Assert a | a.getTest() = e and not exists(a.getMsg())) and kind = "assert" and what = "test"
)
and
// These require parentheses
(not e instanceof Yield and not e instanceof YieldFrom and not e instanceof GeneratorExp) and
l = e.getLocation() and l.getStartLine() = l.getEndLine()
where
e.isParenthesized() and
not e instanceof Tuple and
(
exists(If i | i.getTest() = e) and kind = "if" and what = "condition"
or
exists(While w | w.getTest() = e) and kind = "while" and what = "condition"
or
exists(Return r | r.getValue() = e) and kind = "return" and what = "value"
or
exists(Assert a | a.getTest() = e and not exists(a.getMsg())) and
kind = "assert" and
what = "test"
) and
// These require parentheses
(not e instanceof Yield and not e instanceof YieldFrom and not e instanceof GeneratorExp) and
l = e.getLocation() and
l.getStartLine() = l.getEndLine()
select e, "Parenthesized " + what + " in '" + kind + "' statement."

View File

@@ -15,16 +15,15 @@
import python
predicate is_condition(Expr cond) {
exists(If i | i.getTest() = cond) or
exists(IfExp ie | ie.getTest() = cond)
exists(If i | i.getTest() = cond) or
exists(IfExp ie | ie.getTest() = cond)
}
/* Treat certain unmodified builtins as constants as well. */
predicate effective_constant(Name cond) {
exists(GlobalVariable var | var = cond.getVariable() and not exists(NameNode f | f.defines(var)) |
var.getId() = "True" or var.getId() = "False" or var.getId() = "NotImplemented"
var.getId() = "True" or var.getId() = "False" or var.getId() = "NotImplemented"
)
}
@@ -34,9 +33,10 @@ predicate test_makes_code_unreachable(Expr cond) {
exists(While w | w.getTest() = cond and w.getStmt(0).isUnreachable())
}
from Expr cond
where is_condition(cond) and (cond.isConstant() or effective_constant(cond)) and
/* Ignore cases where test makes code unreachable, as that is handled in different query */
not test_makes_code_unreachable(cond)
where
is_condition(cond) and
(cond.isConstant() or effective_constant(cond)) and
/* Ignore cases where test makes code unreachable, as that is handled in different query */
not test_makes_code_unreachable(cond)
select cond, "Testing a constant will always give the same result."

View File

@@ -9,7 +9,9 @@
* @precision medium
* @id py/missing-docstring
*/
/* NOTE: precision of 'medium' reflects the lack of precision in the underlying rule.
/*
* NOTE: precision of 'medium' reflects the lack of precision in the underlying rule.
* Do we care whether a function has a docstring? That often depends on the reader of that docstring.
*/
@@ -18,25 +20,26 @@ import python
predicate needs_docstring(Scope s) {
s.isPublic() and
(
not s instanceof Function
or
function_needs_docstring(s)
not s instanceof Function
or
function_needs_docstring(s)
)
}
predicate function_needs_docstring(Function f) {
not exists(FunctionObject fo, FunctionObject base | fo.overrides(base) and fo.getFunction() = f |
not function_needs_docstring(base.getFunction())) and
not function_needs_docstring(base.getFunction())
) and
f.getName() != "lambda" and
(f.getMetrics().getNumberOfLinesOfCode() - count(f.getADecorator())) > 2
and not exists(PythonPropertyObject p |
(f.getMetrics().getNumberOfLinesOfCode() - count(f.getADecorator())) > 2 and
not exists(PythonPropertyObject p |
p.getGetter().getFunction() = f or
p.getSetter().getFunction() = f
)
}
string scope_type(Scope s) {
result = "Module" and s instanceof Module and not ((Module)s).isPackage()
result = "Module" and s instanceof Module and not s.(Module).isPackage()
or
result = "Class" and s instanceof Class
or
@@ -46,5 +49,3 @@ string scope_type(Scope s) {
from Scope s
where needs_docstring(s) and not exists(s.getDocString())
select s, scope_type(s) + " " + s.getName() + " does not have a docstring"

View File

@@ -19,9 +19,9 @@ string message() {
}
predicate exec_function_call(Call c) {
exists(GlobalVariable exec | exec = ((Name)c.getFunc()).getVariable() and exec.getId() = "exec")
exists(GlobalVariable exec | exec = c.getFunc().(Name).getVariable() and exec.getId() = "exec")
}
from AstNode exec
where exec_function_call(exec) or exec instanceof Exec
select exec, message()
select exec, message()

View File

@@ -15,16 +15,19 @@ import python
predicate is_a_string_type(ClassObject seqtype) {
seqtype = theBytesType() and major_version() = 2
or
seqtype = theUnicodeType()
or
seqtype = theUnicodeType()
}
from For loop, ControlFlowNode iter, Object str, Object seq, ControlFlowNode seq_origin, ClassObject strtype, ClassObject seqtype, ControlFlowNode str_origin
where loop.getIter().getAFlowNode() = iter and
iter.refersTo(str, strtype, str_origin) and
iter.refersTo(seq, seqtype, seq_origin) and
is_a_string_type(strtype) and
seqtype.isIterable() and
not is_a_string_type(seqtype)
select loop, "Iteration over $@, of class " + seqtype.getName() + ", may also iterate over $@.", seq_origin, "sequence", str_origin, "string"
from
For loop, ControlFlowNode iter, Object str, Object seq, ControlFlowNode seq_origin,
ClassObject strtype, ClassObject seqtype, ControlFlowNode str_origin
where
loop.getIter().getAFlowNode() = iter and
iter.refersTo(str, strtype, str_origin) and
iter.refersTo(seq, seqtype, seq_origin) and
is_a_string_type(strtype) and
seqtype.isIterable() and
not is_a_string_type(seqtype)
select loop, "Iteration over $@, of class " + seqtype.getName() + ", may also iterate over $@.",
seq_origin, "sequence", str_origin, "string"

View File

@@ -14,18 +14,19 @@
import python
private int len(ExprList el) {
result = count(el.getAnItem())
}
private int len(ExprList el) { result = count(el.getAnItem()) }
predicate mismatched(Assign a, int lcount, int rcount, Location loc, string sequenceType) {
exists(ExprList l, ExprList r |
(a.getATarget().(Tuple).getElts() = l or
a.getATarget().(List).getElts() = l)
and
((a.getValue().(Tuple).getElts() = r and sequenceType = "tuple") or
(a.getValue().(List).getElts() = r and sequenceType = "list"))
and
(
a.getATarget().(Tuple).getElts() = l or
a.getATarget().(List).getElts() = l
) and
(
a.getValue().(Tuple).getElts() = r and sequenceType = "tuple"
or
a.getValue().(List).getElts() = r and sequenceType = "list"
) and
loc = a.getValue().getLocation() and
lcount = len(l) and
rcount = len(r) and
@@ -36,9 +37,10 @@ predicate mismatched(Assign a, int lcount, int rcount, Location loc, string sequ
predicate mismatched_tuple_rhs(Assign a, int lcount, int rcount, Location loc) {
exists(ExprList l, TupleObject r, AstNode origin |
(a.getATarget().(Tuple).getElts() = l or
a.getATarget().(List).getElts() = l)
and
(
a.getATarget().(Tuple).getElts() = l or
a.getATarget().(List).getElts() = l
) and
a.getValue().refersTo(r, origin) and
loc = origin.getLocation() and
lcount = len(l) and
@@ -48,11 +50,12 @@ predicate mismatched_tuple_rhs(Assign a, int lcount, int rcount, Location loc) {
)
}
from Assign a, int lcount, int rcount, Location loc, string sequenceType
where
mismatched(a, lcount, rcount, loc, sequenceType)
or
mismatched_tuple_rhs(a, lcount, rcount, loc) and
sequenceType = "tuple"
select a, "Left hand side of assignment contains " + lcount + " variables, but right hand side is a $@ of length " + rcount + "." , loc, sequenceType
select a,
"Left hand side of assignment contains " + lcount +
" variables, but right hand side is a $@ of length " + rcount + ".", loc, sequenceType

View File

@@ -22,14 +22,14 @@ Object aFunctionLocalsObject() {
)
}
predicate modification_of_locals(ControlFlowNode f) {
f.(SubscriptNode).getObject().refersTo(aFunctionLocalsObject()) and (f.isStore() or f.isDelete())
f.(SubscriptNode).getObject().refersTo(aFunctionLocalsObject()) and
(f.isStore() or f.isDelete())
or
exists(string mname, AttrNode attr |
attr = f.(CallNode).getFunction() and
attr.getObject(mname).refersTo(aFunctionLocalsObject(), _) |
attr.getObject(mname).refersTo(aFunctionLocalsObject(), _)
|
mname = "pop" or
mname = "popitem" or
mname = "update" or
@@ -39,5 +39,4 @@ predicate modification_of_locals(ControlFlowNode f) {
from AstNode a, ControlFlowNode f
where modification_of_locals(f) and a = f.getNode()
select a, "Modification of the locals() dictionary will have no effect on the local variables."

View File

@@ -10,20 +10,21 @@
* @precision very-high
* @id py/nested-loops-with-same-variable
*/
import python
predicate loop_variable(For f, Variable v) {
f.getTarget().defines(v)
}
predicate loop_variable(For f, Variable v) { f.getTarget().defines(v) }
predicate variableUsedInNestedLoops(For inner, For outer, Variable v) {
/* Only treat loops in body as inner loops. Loops in the else clause are ignored. */
outer.getBody().contains(inner) and loop_variable(inner, v) and loop_variable(outer, v)
outer.getBody().contains(inner) and
loop_variable(inner, v) and
loop_variable(outer, v) and
/* Ignore cases where there is no use of the variable or the only use is in the inner loop */
and exists(Name n | n.uses(v) and outer.contains(n) and not inner.contains(n))
exists(Name n | n.uses(v) and outer.contains(n) and not inner.contains(n))
}
from For inner, For outer, Variable v
where variableUsedInNestedLoops(inner, outer, v)
select inner, "Nested for statement uses loop variable '" + v.getId() + "' of enclosing $@.",
outer, "for statement"
select inner, "Nested for statement uses loop variable '" + v.getId() + "' of enclosing $@.", outer,
"for statement"

View File

@@ -19,18 +19,18 @@ predicate loop_variable_ssa(For f, Variable v, SsaVariable s) {
predicate variableUsedInNestedLoops(For inner, For outer, Variable v, Name n) {
/* Ignore cases where there is no use of the variable or the only use is in the inner loop. */
outer.contains(n)
and not inner.contains(n)
outer.contains(n) and
not inner.contains(n) and
/* Only treat loops in body as inner loops. Loops in the else clause are ignored. */
and outer.getBody().contains(inner)
and exists(SsaVariable s |
loop_variable_ssa(inner, v, s.getAnUltimateDefinition())
and loop_variable_ssa(outer, v, _)
and s.getAUse().getNode() = n
outer.getBody().contains(inner) and
exists(SsaVariable s |
loop_variable_ssa(inner, v, s.getAnUltimateDefinition()) and
loop_variable_ssa(outer, v, _) and
s.getAUse().getNode() = n
)
}
from For inner, For outer, Variable v, Name n
where variableUsedInNestedLoops(inner, outer, v, n)
select inner, "Nested for statement $@ loop variable '" + v.getId() + "' of enclosing $@.", n, "uses",
outer, "for statement"
select inner, "Nested for statement $@ loop variable '" + v.getId() + "' of enclosing $@.", n,
"uses", outer, "for statement"

View File

@@ -14,10 +14,12 @@
import python
from For loop, ControlFlowNode iter, Value v, ClassValue t, ControlFlowNode origin
where loop.getIter().getAFlowNode() = iter and
iter.pointsTo(_, v, origin) and v.getClass() = t and
not t.isIterable() and not t.failedInference(_) and
not v = Value::named("None") and
not t.isDescriptorType()
where
loop.getIter().getAFlowNode() = iter and
iter.pointsTo(_, v, origin) and
v.getClass() = t and
not t.isIterable() and
not t.failedInference(_) and
not v = Value::named("None") and
not t.isDescriptorType()
select loop, "$@ of class '$@' may be used in for-loop.", origin, "Non-iterator", t, t.getName()

View File

@@ -12,8 +12,8 @@
*/
import python
predicate assignment(AssignStmt a, Expr left, Expr right)
{
predicate assignment(AssignStmt a, Expr left, Expr right) {
a.getATarget() = left and a.getValue() = right
}
@@ -23,7 +23,8 @@ predicate corresponding(Expr left, Expr right) {
exists(Attribute la, Attribute ra |
corresponding(la, ra) and
left = la.getObject() and
right = ra.getObject())
right = ra.getObject()
)
}
predicate same_value(Expr left, Expr right) {
@@ -33,9 +34,7 @@ predicate same_value(Expr left, Expr right) {
}
predicate maybe_defined_in_outer_scope(Name n) {
exists(SsaVariable v | v.getAUse().getNode() = n |
v.maybeUndefined()
)
exists(SsaVariable v | v.getAUse().getNode() = n | v.maybeUndefined())
}
Variable relevant_var(Name n) {
@@ -50,17 +49,18 @@ predicate same_name(Name n1, Name n2) {
not maybe_defined_in_outer_scope(n2)
}
ClassObject value_type(Attribute a) {
a.getObject().refersTo(_, result, _)
}
ClassObject value_type(Attribute a) { a.getObject().refersTo(_, result, _) }
predicate is_property_access(Attribute a) {
value_type(a).lookupAttribute(a.getName()) instanceof PropertyObject
}
predicate same_attribute(Attribute a1, Attribute a2) {
corresponding(a1, a2) and a1.getName() = a2.getName() and same_value(a1.getObject(), a2.getObject()) and
exists(value_type(a1)) and not is_property_access(a1)
corresponding(a1, a2) and
a1.getName() = a2.getName() and
same_value(a1.getObject(), a2.getObject()) and
exists(value_type(a1)) and
not is_property_access(a1)
}
int pyflakes_commented_line(File file) {
@@ -72,21 +72,24 @@ int pyflakes_commented_line(File file) {
predicate pyflakes_commented(AssignStmt assignment) {
exists(Location loc |
assignment.getLocation() = loc and
loc.getStartLine() = pyflakes_commented_line(loc.getFile()))
loc.getStartLine() = pyflakes_commented_line(loc.getFile())
)
}
predicate side_effecting_lhs(Attribute lhs) {
exists(ClassObject cls, ClassObject decl |
lhs.getObject().refersTo(_, cls, _) and
decl = cls.getAnImproperSuperType() and
not decl.isBuiltin() |
not decl.isBuiltin()
|
decl.declaresAttribute("__setattr__")
)
}
from AssignStmt a, Expr left, Expr right
where assignment(a, left, right)
and same_value(left, right)
and not pyflakes_commented(a) and
not side_effecting_lhs(left)
where
assignment(a, left, right) and
same_value(left, right) and
not pyflakes_commented(a) and
not side_effecting_lhs(left)
select a, "This assignment assigns a variable to itself."

View File

@@ -14,12 +14,12 @@ import python
from AstNode node, string kind
where
not node.getScope() instanceof Function and
(
node instanceof Return and kind = "return"
or
node instanceof Yield and kind = "yield"
or
node instanceof YieldFrom and kind = "yield from"
)
not node.getScope() instanceof Function and
(
node instanceof Return and kind = "return"
or
node instanceof Yield and kind = "yield"
or
node instanceof YieldFrom and kind = "yield from"
)
select node, "'" + kind + "' is used outside a function."

View File

@@ -14,14 +14,12 @@
import python
predicate calls_close(Call c) { exists(Attribute a | c.getFunc() = a and a.getName() = "close") }
predicate calls_close(Call c) {
exists (Attribute a | c.getFunc() = a and a.getName() = "close")
}
predicate
only_stmt_in_finally(Try t, Call c) {
exists(ExprStmt s | t.getAFinalstmt() = s and s.getValue() = c and strictcount(t.getAFinalstmt()) = 1)
predicate only_stmt_in_finally(Try t, Call c) {
exists(ExprStmt s |
t.getAFinalstmt() = s and s.getValue() = c and strictcount(t.getAFinalstmt()) = 1
)
}
predicate points_to_context_manager(ControlFlowNode f, ClassObject cls) {
@@ -30,8 +28,12 @@ predicate points_to_context_manager(ControlFlowNode f, ClassObject cls) {
}
from Call close, Try t, ClassObject cls
where only_stmt_in_finally(t, close) and calls_close(close) and
exists(ControlFlowNode f | f = close.getFunc().getAFlowNode().(AttrNode).getObject() |
points_to_context_manager(f, cls))
select close, "Instance of context-manager class $@ is closed in a finally block. Consider using 'with' statement.", cls, cls.getName()
where
only_stmt_in_finally(t, close) and
calls_close(close) and
exists(ControlFlowNode f | f = close.getFunc().getAFlowNode().(AttrNode).getObject() |
points_to_context_manager(f, cls)
)
select close,
"Instance of context-manager class $@ is closed in a finally block. Consider using 'with' statement.",
cls, cls.getName()

View File

@@ -14,11 +14,16 @@
import python
predicate func_with_side_effects(Expr e) {
exists(string name |
name = ((Attribute)e).getName() or name = ((Name)e).getId() |
name = "print" or name = "write" or name = "append" or
name = "pop" or name = "remove" or name = "discard" or
name = "delete" or name = "close" or name = "open" or
exists(string name | name = e.(Attribute).getName() or name = e.(Name).getId() |
name = "print" or
name = "write" or
name = "append" or
name = "pop" or
name = "remove" or
name = "discard" or
name = "delete" or
name = "close" or
name = "open" or
name = "exit"
)
}
@@ -29,7 +34,7 @@ predicate probable_side_effect(Expr e) {
or
e instanceof YieldFrom
or
e instanceof Call and func_with_side_effects(((Call)e).getFunc())
e instanceof Call and func_with_side_effects(e.(Call).getFunc())
}
from Assert a, Expr e

View File

@@ -14,8 +14,7 @@
import python
predicate understood_attribute(Attribute attr, ClassObject cls, ClassObject attr_cls) {
exists(string name |
attr.getName() = name |
exists(string name | attr.getName() = name |
attr.getObject().refersTo(_, cls, _) and
cls.attributeRefersTo(name, _, attr_cls, _)
)
@@ -37,15 +36,19 @@ predicate maybe_side_effecting_attribute(Attribute attr) {
predicate side_effecting_descriptor_type(ClassObject descriptor) {
descriptor.isDescriptorType() and
/* Technically all descriptor gets have side effects,
* but some are indicative of a missing call and
* we want to treat them as having no effect. */
not descriptor = thePyFunctionType() and
not descriptor = theStaticMethodType() and
not descriptor = theClassMethodType()
/*
* Technically all descriptor gets have side effects,
* but some are indicative of a missing call and
* we want to treat them as having no effect.
*/
not descriptor = thePyFunctionType() and
not descriptor = theStaticMethodType() and
not descriptor = theClassMethodType()
}
/** Side effecting binary operators are rare, so we assume they are not
/**
* Side effecting binary operators are rare, so we assume they are not
* side-effecting unless we know otherwise.
*/
predicate side_effecting_binary(Expr b) {
@@ -53,20 +56,22 @@ predicate side_effecting_binary(Expr b) {
binary_operator_special_method(b, sub, cls, method_name)
or
comparison_special_method(b, sub, cls, method_name)
|
|
method_name = special_method() and
cls.hasAttribute(method_name)
and
cls.hasAttribute(method_name) and
not exists(ClassObject declaring |
declaring.declaresAttribute(method_name)
and declaring = cls.getAnImproperSuperType() and
declaring.isBuiltin() and not declaring = theObjectType()
declaring.declaresAttribute(method_name) and
declaring = cls.getAnImproperSuperType() and
declaring.isBuiltin() and
not declaring = theObjectType()
)
)
}
pragma[nomagic]
private predicate binary_operator_special_method(BinaryExpr b, Expr sub, ClassObject cls, string method_name) {
private predicate binary_operator_special_method(
BinaryExpr b, Expr sub, ClassObject cls, string method_name
) {
method_name = special_method() and
sub = b.getLeft() and
method_name = b.getOp().getSpecialMethodName() and
@@ -89,19 +94,17 @@ private string special_method() {
}
predicate is_notebook(File f) {
exists(Comment c |
c.getLocation().getFile() = f |
exists(Comment c | c.getLocation().getFile() = f |
c.getText().regexpMatch("#\\s*<nbformat>.+</nbformat>\\s*")
)
}
/** Expression (statement) in a jupyter/ipython notebook */
predicate in_notebook(Expr e) {
is_notebook(e.getScope().(Module).getFile())
}
predicate in_notebook(Expr e) { is_notebook(e.getScope().(Module).getFile()) }
FunctionObject assertRaises() {
result = ModuleObject::named("unittest").attr("TestCase").(ClassObject).lookupAttribute("assertRaises")
result =
ModuleObject::named("unittest").attr("TestCase").(ClassObject).lookupAttribute("assertRaises")
}
/** Holds if expression `e` is in a `with` block that tests for exceptions being raised. */
@@ -122,13 +125,10 @@ predicate python2_print(Expr e) {
predicate no_effect(Expr e) {
not e instanceof StrConst and
not ((StrConst)e).isDocString() and
not e.(StrConst).isDocString() and
not e.hasSideEffects() and
forall(Expr sub |
sub = e.getASubExpression*()
|
not side_effecting_binary(sub)
and
forall(Expr sub | sub = e.getASubExpression*() |
not side_effecting_binary(sub) and
not maybe_side_effecting_attribute(sub)
) and
not in_notebook(e) and
@@ -139,4 +139,3 @@ predicate no_effect(Expr e) {
from ExprStmt stmt
where no_effect(stmt.getValue())
select stmt, "This statement has no effect."

View File

@@ -13,17 +13,17 @@
import python
predicate string_concat_in_loop(BinaryExpr b) {
b.getOp() instanceof Add
and
b.getOp() instanceof Add and
exists(SsaVariable d, SsaVariable u, BinaryExprNode add, ClassObject str_type |
add.getNode() = b and d = u.getAnUltimateDefinition() |
d.getDefinition().(DefinitionNode).getValue() = add and u.getAUse() = add.getAnOperand() and
add.getAnOperand().refersTo(_, str_type, _) and
(str_type = theBytesType() or str_type = theUnicodeType())
add.getNode() = b and d = u.getAnUltimateDefinition()
|
d.getDefinition().(DefinitionNode).getValue() = add and
u.getAUse() = add.getAnOperand() and
add.getAnOperand().refersTo(_, str_type, _) and
(str_type = theBytesType() or str_type = theUnicodeType())
)
}
from BinaryExpr b, Stmt s
where string_concat_in_loop(b) and s.getASubExpression() = b
select s, "String concatenation in a loop is quadratic in the number of iterations."

View File

@@ -13,10 +13,10 @@
import python
predicate main_eq_name(If i) {
exists(Name n, StrConst m, Compare c |
i.getTest() = c and c.getLeft() = n and
i.getTest() = c and
c.getLeft() = n and
c.getAComparator() = m and
n.getId() = "__name__" and
m.getText() = "__main__"
@@ -24,12 +24,16 @@ predicate main_eq_name(If i) {
}
predicate is_print_stmt(Stmt s) {
s instanceof Print or
exists(ExprStmt e, Call c, Name n | e = s and c = e.getValue() and n = c.getFunc() and n.getId() = "print")
s instanceof Print
or
exists(ExprStmt e, Call c, Name n |
e = s and c = e.getValue() and n = c.getFunc() and n.getId() = "print"
)
}
from Stmt p
where is_print_stmt(p) and
exists(ModuleObject m | m.getModule() = p.getScope() and m.getKind() = "module") and
not exists(If i | main_eq_name(i) and i.getASubStatement().getASubStatement*() = p)
where
is_print_stmt(p) and
exists(ModuleObject m | m.getModule() = p.getScope() and m.getKind() = "module") and
not exists(If i | main_eq_name(i) and i.getASubStatement().getASubStatement*() = p)
select p, "Print statement may execute during import."

View File

@@ -12,7 +12,6 @@
* @id py/unnecessary-delete
*/
import python
from Delete del, Expr e, Function f
@@ -23,11 +22,14 @@ where
not e instanceof Subscript and
not e instanceof Attribute and
not exists(Stmt s | s.(While).contains(del) or s.(For).contains(del)) and
/* False positive: calling `sys.exc_info` within a function results in a
reference cycle,and an explicit call to `del` helps break this cycle. */
/*
* False positive: calling `sys.exc_info` within a function results in a
* reference cycle, and an explicit call to `del` helps break this cycle.
*/
not exists(FunctionObject ex |
ex.hasLongName("sys.exc_info") and
ex.getACall().getScope() = f
)
select del, "Unnecessary deletion of local variable $@ in function $@.",
e.getLocation(), e.toString(), f.getLocation(), f.getName()
select del, "Unnecessary deletion of local variable $@ in function $@.", e.getLocation(),
e.toString(), f.getLocation(), f.getName()

View File

@@ -14,9 +14,11 @@ import python
from Stmt loop, StmtList body, StmtList clause, string kind
where
(exists(For f | f = loop | clause = f.getOrelse() and body = f.getBody() and kind = "for")
or
exists(While w | w = loop | clause = w.getOrelse() and body = w.getBody() and kind = "while")
)
and not exists(Break b | body.contains(b))
select loop, "This '" + kind + "' statement has a redundant 'else' as no 'break' is present in the body."
(
exists(For f | f = loop | clause = f.getOrelse() and body = f.getBody() and kind = "for")
or
exists(While w | w = loop | clause = w.getOrelse() and body = w.getBody() and kind = "while")
) and
not exists(Break b | body.contains(b))
select loop,
"This '" + kind + "' statement has a redundant 'else' as no 'break' is present in the body."

View File

@@ -13,21 +13,20 @@
import python
predicate is_doc_string(ExprStmt s) {
s.getValue() instanceof Unicode or s.getValue() instanceof Bytes
s.getValue() instanceof Unicode or s.getValue() instanceof Bytes
}
predicate has_doc_string(StmtList stmts) {
stmts.getParent() instanceof Scope
and
stmts.getParent() instanceof Scope and
is_doc_string(stmts.getItem(0))
}
from Pass p, StmtList list
where list.getAnItem() = p and
(
strictcount(list.getAnItem()) = 2 and not has_doc_string(list)
or
strictcount(list.getAnItem()) > 2
)
where
list.getAnItem() = p and
(
strictcount(list.getAnItem()) = 2 and not has_doc_string(list)
or
strictcount(list.getAnItem()) > 2
)
select p, "Unnecessary 'pass' statement."

View File

@@ -13,7 +13,8 @@
import python
from Call call, ClassObject ex
where call.getFunc().refersTo(ex) and ex.getAnImproperSuperType() = theExceptionType()
and exists(ExprStmt s | s.getValue() = call)
where
call.getFunc().refersTo(ex) and
ex.getAnImproperSuperType() = theExceptionType() and
exists(ExprStmt s | s.getValue() = call)
select call, "Instantiating an exception, but not raising it, has no effect"

View File

@@ -13,4 +13,6 @@ import python
from CallNode call, string name
where call.getFunction().refersTo(Object::quitter(name))
select call, "The '" + name + "' site.Quitter object may not exist if the 'site' module is not loaded or is modified."
select call,
"The '" + name +
"' site.Quitter object may not exist if the 'site' module is not loaded or is modified."