Skip to content

Commit

Permalink
Merge pull request #12 from returntocorp/feature/more-rules-and-tests
Browse files Browse the repository at this point in the history
Feature/more rules and tests
  • Loading branch information
DrewDennison committed Feb 1, 2020
2 parents f607714 + 1d82b5f commit 81f1734
Show file tree
Hide file tree
Showing 36 changed files with 734 additions and 6 deletions.
4 changes: 2 additions & 2 deletions .circleci/config.yml
Expand Up @@ -4,9 +4,9 @@ jobs:
docker:
- image: returntocorp/sgrep
steps:
- run: apk add make
- checkout
- run: sgrep-lint --validate python .
- run: sgrep-lint --validate c .
- run: make test
workflows:
version: 2.1
build_and_test:
Expand Down
4 changes: 4 additions & 0 deletions Makefile
@@ -0,0 +1,4 @@
test:
sgrep-lint --validate --config=./python .
sgrep-lint --validate --config=./c .
./test.py --ignore-todo .
17 changes: 17 additions & 0 deletions python/compatibility/python37.py
@@ -0,0 +1,17 @@
import os

# ruleid:python37-compatability-os-module
os.pwrite('a')

if hasattr(os, 'pwrite'):
# OK
os.pwrite('a')


if hasattr(os, 'pwritev'):
# OK
os.pwritev('a')


# ruleid:python37-compatibility-os2-ok2
os.pwritev('b')
19 changes: 19 additions & 0 deletions python/deadcode/baseclass-attribute-override.py
@@ -0,0 +1,19 @@

class A:
def method1(self, args):
pass


class A2:
def method2(self, args):
pass


class B:
def method1(self, args):
print('hello there')

# todoruleid: baseclass-attribute-override
class C(A, B):
def __init__():
print('initialized')
17 changes: 17 additions & 0 deletions python/deadcode/baseclass-attribute-override.yaml
@@ -0,0 +1,17 @@
rules:
- id: baseclass-attribute-override
patterns:
- pattern: |
class $A(...):
def $F(...):
...
...
class $B(...):
def $F(...):
...
...
class $C(..., $A, $B, ...):
...
message: "Class $C inherits from both `$A` and `$B` which both have a method named `$F`; one of these methods will be overwritten"
languages: [python]
severity: WARNING
3 changes: 3 additions & 0 deletions python/deadcode/missing-fstring.py
@@ -0,0 +1,3 @@
x = y
print('hi')
print('now {x} is {y}')
10 changes: 10 additions & 0 deletions python/deadcode/missing-fstring.yaml
@@ -0,0 +1,10 @@
rules:
- id: should-be-fstring
patterns:
- pattern: |
$X = $Y
...
print('...{$X}...')
message: "possibly missing an f-string specifier for string containing variable $X"
languages: [python]
severity: WARNING
19 changes: 19 additions & 0 deletions python/deadcode/return.py
@@ -0,0 +1,19 @@

# ruleid: return-not-in-function
return 5


def alwaysblue():
if isblue():
return 'blue'
# todoruleid: code-after-unconditional-return
return 'red'
return 'green'


def alwaysblue():
if isblue():
return 'blue'
# todoruleid: code-after-unconditional-return
return 'red'
x = 5
18 changes: 18 additions & 0 deletions python/deadcode/return.yaml
@@ -0,0 +1,18 @@
rules:
- id: code-after-unconditional-return
patterns:
- pattern: |
return $X
$S
message: "code after return statement will not be executed"
languages: [python]
severity: WARNING
- id: return-not-in-function
patterns:
- pattern-not-inside: |
def $F(...):
...
- pattern: return $X
message: "`return` only makes sense inside a function"
languages: [python]
severity: WARNING
23 changes: 23 additions & 0 deletions python/deadcode/useless-assign.py
@@ -0,0 +1,23 @@
d = {}
z = {}
a = {}
for i in xrange(100):
# ruleid: useless-assignment-keyed
d[i] = z[i]
d[i] = z[i]
d[i+1] = z[i]

for i in xrange(100):
# todoruleid: useless-assignment-keyed
da[i*1][j] = z[i]
da[i*1][j] = z[i]
da[i*4] = z[i]

# todoruleid: useless-assignment
x = 5
x = 5

x = y
x = y()

y() = y()
21 changes: 21 additions & 0 deletions python/deadcode/useless-assign.yaml
@@ -0,0 +1,21 @@
rules:
- id: useless-assignment-keyed
patterns:
- pattern-either:
- pattern: |
$X[$Y] = ...
$X[$Y] = ...
- pattern: |
$X[$Y][$Z] = ...
$X[$Y][$Z] = ...
message: "key `$Y` in `$X` is uselessly assigned the same value twice"
languages: [python]
severity: WARNING
- id: useless-assignment
patterns:
- pattern: |
$X = $Y
$X = $Y
message: "`$X` is uselessly assigned to the same value (`$Y`) twice"
languages: [python]
severity: WARNING
2 changes: 1 addition & 1 deletion python/deadcode/useless-eqeq.yaml
Expand Up @@ -11,6 +11,6 @@ rules:
- pattern: $X == $X
- pattern: $X != $X
- pattern-not: 1 == 1
message: "useless comparison operation `$X == $X` or `$X != $X`; possible bug?"
message: "useless comparison operation `$X == $X` or `$X != $X`; if testing for floating point NaN, use `math.isnan`, or `cmath.isnan` if the number is complex."
languages: [python]
severity: ERROR
39 changes: 39 additions & 0 deletions python/deadcode/useless-ifelse.py
@@ -0,0 +1,39 @@
a, b, c = 1

# ruleid: useless-if-conditional
if a:
print('1')
elif a:
print('2')

# ruleid: useless-if-body
if a:
print('1')
else:
print('1')

# ruleid: useless-if-body
if a:
print('1')
elif b:
print('1')


# todoruleid: useless-if-body
if a:
print('this is a')
elif b:
print('this is b')
elif c:
print('this is c')
elif d:
print('this is d')


if a:
print('this is a')
# ruleid: useless-if-body
elif b:
print('this is b')
elif c:
print('this is b')
35 changes: 35 additions & 0 deletions python/deadcode/useless-ifelse.yaml
@@ -0,0 +1,35 @@
rules:
- id: useless-if-conditional
patterns:
- pattern-either:
- pattern: |
if $X:
...
elif $X:
...
message: "if block checks for the same condition on both branches (`$X`)"
languages: [python]
severity: WARNING
- id: useless-if-body
patterns:
- pattern-either:
- pattern: |
if $X:
$S
elif $Y:
$S
- pattern: |
if $X:
$S
else:
$S
- pattern: |
if $X:
$S
elif $Z:
...
elif $Y:
$S
message: "useless if statment; both blocks have the same body"
languages: [python]
severity: WARNING
21 changes: 21 additions & 0 deletions python/deadcode/useless-innerfunction.py
@@ -0,0 +1,21 @@
# todoruleid:useless-inner-function
def A():
print_error('test')

def B():
print_error('again')

def C():
print_error('another')
return None

# todoruleid:useless-inner-function
def A():
print_error('test')

def B():
print_error('again')

def C():
print_error('another')
return B(), C()
19 changes: 19 additions & 0 deletions python/deadcode/useless-innerfunction.yaml
@@ -0,0 +1,19 @@
rules:
- id: useless-inner-function
patterns:
- pattern-not-inside: |
def $F(...):
...
def $F2(...):
...
...
$F2
- pattern: |
def $F(...):
...
def $F2(...):
...
...
message: "function `$F2` is defined inside a function but never used"
languages: [python]
severity: ERROR
12 changes: 12 additions & 0 deletions python/deadcode/useless-literal.py
@@ -0,0 +1,12 @@
# todoruleid: useless-literal-dict
d = dict(1: 'a', 2: 'b', 1: 'a')
# todoruleid: useless-literal-set
d = set(1: 'a', 2: 'b', 1: 'a')

# todoruleid: useless-literal-dict
d = {1: 'a', 2: 'b', 1: 'a'}
# todoruleid: useless-literal-dict
d = {'a': 1, 'a': 1}

# OK
d = {1: 'a', 2: 'b', 3: 'a'}
18 changes: 18 additions & 0 deletions python/deadcode/useless-literal.yaml
@@ -0,0 +1,18 @@
rules:
- id: useless-literal-dict
patterns:
- pattern-either:
# - pattern: |
# dict(..., $X: $A, ..., $X: $B, ...)
- pattern: |
{..., $X: $A, ..., $X: $B, ...}
message: "key `$X` is uselessly assigned twice"
languages: [python]
severity: WARNING
- id: useless-literal-set
patterns:
# - pattern: |
# set(..., $X: $A, ..., $X: $B, ...)
message: "`$X` is uselessly assigned twice inside the creation of the set"
languages: [python]
severity: ERROR
24 changes: 24 additions & 0 deletions python/exceptions/exceptions.py
@@ -0,0 +1,24 @@
# ruleid:raise-not-base-exception
raise "error here"

# todoruleid:raise-not-base-exception
raise 5


class Foobar:
x = 5


# todoruleid:raise-not-base-exception
raise Foobar()


class Foobar2(BaseException):
x = 5


# OK
raise Foobar2()

# OK
raise Exception()
16 changes: 16 additions & 0 deletions python/exceptions/exceptions.yaml
@@ -0,0 +1,16 @@
rules:
- id: raise-not-base-exception
patterns:
- pattern-either:
- pattern: raise "..."
#- pattern: |
# raise $X: int
#- pattern: |
# raise $X: float
# TODO, the second pattern requires sgrep typing support
- pattern: |
$X: BaseException
raise $X(...)
message: "In Python3, a runtime `TypeError` will be thrown if you attempt to raise an object or class which does not inherit from `BaseException`"
languages: [python]
severity: ERROR
13 changes: 13 additions & 0 deletions python/smells/missing-hash-with-eq.py
@@ -0,0 +1,13 @@

# todoruleid:missing-hash-with-eq
class A:
def __eq__(self, someother):
pass


class A2:
def __eq__(self, someother):
pass

def __hash__(self):
pass

0 comments on commit 81f1734

Please sign in to comment.