Merge pull request #2012 from RasmusWL/python-modernise-cls-self-checks

Python: modernise cls self argument name checks
This commit is contained in:
Taus
2019-09-30 15:50:32 +02:00
committed by GitHub
14 changed files with 266 additions and 174 deletions

View File

@@ -1 +1 @@
| Function yes |
| Function Z.yes |

View File

@@ -2,5 +2,5 @@
import python
import semmle.python.libraries.Zope
from ZopeInterfaceMethod f
from ZopeInterfaceMethodValue f
select f.toString()

View File

@@ -1,14 +1,14 @@
edges
| functions_test.py:39:9:39:9 | empty mutable value | functions_test.py:40:5:40:5 | empty mutable value |
| functions_test.py:133:15:133:15 | empty mutable value | functions_test.py:134:5:134:5 | empty mutable value |
| functions_test.py:185:25:185:25 | empty mutable value | functions_test.py:186:5:186:5 | empty mutable value |
| functions_test.py:188:21:188:21 | empty mutable value | functions_test.py:189:5:189:5 | empty mutable value |
| functions_test.py:191:27:191:27 | empty mutable value | functions_test.py:192:25:192:25 | empty mutable value |
| functions_test.py:191:27:191:27 | empty mutable value | functions_test.py:193:21:193:21 | empty mutable value |
| functions_test.py:192:25:192:25 | empty mutable value | functions_test.py:185:25:185:25 | empty mutable value |
| functions_test.py:193:21:193:21 | empty mutable value | functions_test.py:188:21:188:21 | empty mutable value |
| functions_test.py:151:25:151:25 | empty mutable value | functions_test.py:152:5:152:5 | empty mutable value |
| functions_test.py:154:21:154:21 | empty mutable value | functions_test.py:155:5:155:5 | empty mutable value |
| functions_test.py:157:27:157:27 | empty mutable value | functions_test.py:158:25:158:25 | empty mutable value |
| functions_test.py:157:27:157:27 | empty mutable value | functions_test.py:159:21:159:21 | empty mutable value |
| functions_test.py:158:25:158:25 | empty mutable value | functions_test.py:151:25:151:25 | empty mutable value |
| functions_test.py:159:21:159:21 | empty mutable value | functions_test.py:154:21:154:21 | empty mutable value |
#select
| functions_test.py:40:5:40:5 | x | functions_test.py:39:9:39:9 | empty mutable value | functions_test.py:40:5:40:5 | empty mutable value | $@ flows to here and is mutated. | functions_test.py:39:9:39:9 | x | Default value |
| functions_test.py:134:5:134:5 | x | functions_test.py:133:15:133:15 | empty mutable value | functions_test.py:134:5:134:5 | empty mutable value | $@ flows to here and is mutated. | functions_test.py:133:15:133:15 | x | Default value |
| functions_test.py:186:5:186:5 | x | functions_test.py:191:27:191:27 | empty mutable value | functions_test.py:186:5:186:5 | empty mutable value | $@ flows to here and is mutated. | functions_test.py:191:27:191:27 | y | Default value |
| functions_test.py:189:5:189:5 | x | functions_test.py:191:27:191:27 | empty mutable value | functions_test.py:189:5:189:5 | empty mutable value | $@ flows to here and is mutated. | functions_test.py:191:27:191:27 | y | Default value |
| functions_test.py:152:5:152:5 | x | functions_test.py:157:27:157:27 | empty mutable value | functions_test.py:152:5:152:5 | empty mutable value | $@ flows to here and is mutated. | functions_test.py:157:27:157:27 | y | Default value |
| functions_test.py:155:5:155:5 | x | functions_test.py:157:27:157:27 | empty mutable value | functions_test.py:155:5:155:5 | empty mutable value | $@ flows to here and is mutated. | functions_test.py:157:27:157:27 | y | Default value |

View File

@@ -1,2 +1,3 @@
| argument_names.py:17:5:17:24 | Function n_cmethod | Class methods or methods of a type deriving from type should have 'cls', rather than 'self', as their first argument. |
| argument_names.py:32:5:32:20 | Function c_method | Class methods or methods of a type deriving from type should have 'cls', rather than 'y', as their first argument. |
| parameter_names.py:17:5:17:24 | Function n_cmethod | Class methods or methods of a type deriving from type should have 'cls', rather than 'self', as their first parameter. |
| parameter_names.py:22:5:22:21 | Function n_cmethod2 | Class methods or methods of a type deriving from type should have 'cls' as their first parameter. |
| parameter_names.py:37:5:37:20 | Function c_method | Class methods or methods of a type deriving from type should have 'cls', rather than 'y', as their first parameter. |

View File

@@ -1,3 +1,4 @@
| argument_names.py:45:5:45:20 | Function __init__ | Normal methods should have 'self', rather than 'x', as their first parameter. |
| argument_names.py:48:5:48:20 | Function s_method | Normal methods should have 'self', rather than 'y', as their first parameter. |
| om_test.py:71:5:71:19 | Function __repr__ | Normal methods should have at least one parameter (the first of which should be 'self'). |
| parameter_names.py:50:5:50:20 | Function __init__ | Normal methods should have 'self', rather than 'x', as their first parameter. |
| parameter_names.py:53:5:53:20 | Function s_method | Normal methods should have 'self', rather than 'y', as their first parameter. |
| parameter_names.py:56:5:56:20 | Function s_method2 | Normal methods should have at least one parameter (the first of which should be 'self'). |

View File

@@ -1,68 +0,0 @@
# Using name other than 'self' for first argument in methods.
# This shouldn't apply to classmethods (first argument should be 'cls' or similar)
# or static methods (first argument can be anything)
class Normal(object):
def n_ok(self):
pass
@staticmethod
def n_smethod(ok):
pass
# not ok
@classmethod
def n_cmethod(self):
pass
# this is allowed because it has a decorator other than @classmethod
@classmethod
@id
def n_suppress(any_name):
pass
class Class(type):
def __init__(cls):
pass
def c_method(y):
pass
def c_ok(cls):
pass
@id
def c_suppress(any_name):
pass
class NonSelf(object):
def __init__(x):
pass
def s_method(y):
pass
def s_ok(self):
pass
@staticmethod
def s_smethod(ok):
pass
@classmethod
def s_cmethod(cls):
pass
def s_smethod2(ok):
pass
s_smethod2 = staticmethod(s_smethod2)
def s_cmethod2(cls):
pass
s_cmethod2 = classmethod(s_cmethod2)

View File

@@ -134,33 +134,6 @@ def augassign(x = []):
x += ["x"]
#Possible FPs for non-self. ODASA-2439
class C(object):
def _func(f):
return f
_func(x)
#or
@_func
def meth(self):
pass
def dont_care(arg):
pass
class C(object):
meth = dont_care
class Meta(type):
#__new__ is an implicit class method, so the first arg is the metaclass
def __new__(metacls, name, bases, cls_dict):
return super(Meta, metacls).__new__(metacls, name, bases, cls_dict)
#ODASA 3658
from sys import exit
#Consistent returns
@@ -172,14 +145,7 @@ def ok5():
print(e)
exit(EXIT_ERROR)
#ODASA-6062
import zope.interface
class Z(zope.interface.Interface):
def meth(arg):
pass
Z().meth(0)
# indirect modification of parameter with default
def aug_assign_argument(x):

View File

@@ -0,0 +1,119 @@
# Using name other than 'self' for first parameter in methods.
# This shouldn't apply to classmethods (first parameter should be 'cls' or similar)
# or static methods (first parameter can be anything)
class Normal(object):
def n_ok(self):
pass
@staticmethod
def n_smethod(ok):
pass
# not ok
@classmethod
def n_cmethod(self):
pass
# not ok
@classmethod
def n_cmethod2():
pass
# this is allowed because it has a decorator other than @classmethod
@classmethod
@id
def n_suppress(any_name):
pass
class Class(type):
def __init__(cls):
pass
def c_method(y):
pass
def c_ok(cls):
pass
@id
def c_suppress(any_name):
pass
class NonSelf(object):
def __init__(x):
pass
def s_method(y):
pass
def s_method2():
pass
def s_ok(self):
pass
@staticmethod
def s_smethod(ok):
pass
@classmethod
def s_cmethod(cls):
pass
def s_smethod2(ok):
pass
s_smethod2 = staticmethod(s_smethod2)
def s_cmethod2(cls):
pass
s_cmethod2 = classmethod(s_cmethod2)
#Possible FPs for non-self. ODASA-2439
class Acceptable1(object):
def _func(f):
return f
_func(x)
class Acceptable2(object):
def _func(f):
return f
@_func
def meth(self):
pass
# Handling methods defined in a different scope than the class it belongs to,
# gets problmematic since we need to show the full-path from method definition
# to actually adding it to the class. We tried to enable warnings for these in
# September 2019, but ended up sticking to the decision from ODASA-2439 (where
# results are both obvious and useful to the end-user).
def dont_care(arg):
pass
class Acceptable3(object):
meth = dont_care
# OK
class Meta(type):
#__new__ is an implicit class method, so the first arg is the metaclass
def __new__(metacls, name, bases, cls_dict):
return super(Meta, metacls).__new__(metacls, name, bases, cls_dict)
#ODASA-6062
import zope.interface
class Z(zope.interface.Interface):
def meth(arg):
pass
Z().meth(0)