@@ -28,12 +28,39 @@ def _isStringClass(self, c):
28
28
else :
29
29
return False
30
30
31
+ def _isTupleClass (self , c ):
32
+ className = str (type (c ))
33
+ return className in ["<class '_ast.Tuple'>" , "<class 'ast.Tuple'>" ]
34
+
31
35
def _getStringValue (self , c ):
36
+ """Parses a single string value in the AST tree"""
32
37
if str (type (c )) in ["<class '_ast.Str'>" , "<class 'str'>" ]:
33
38
return c .s
34
39
else :
35
40
return c .value
36
41
42
+ def _getStringValuesAsList (self , c ):
43
+ """Parses a single string value or tuple of strings in an AST
44
+ tree as a list of strings."""
45
+ def _get_single (c ):
46
+ classname = str (type (c ))
47
+ if classname in ["<class '_ast.Str'>" , "<class 'str'>" ]:
48
+ return [c .s ]
49
+ elif classname in [ "<class '_ast.Constant'>" , "<class 'ast.Constant'>" ]:
50
+ return [c .value ]
51
+ else :
52
+ return []
53
+
54
+ classname = str (type (c ))
55
+ if classname in ["<class '_ast.Str'>" , "<class 'str'>" ,
56
+ "<class '_ast.Constant'>" , "<class 'ast.Constant'>" ]:
57
+ return _get_single (c )
58
+ elif classname in ["<class '_ast.Tuple'>" , "<class 'ast.Tuple'>" ]:
59
+ result = []
60
+ for element in c .elts :
61
+ result .extend (_get_single (element ))
62
+ return result
63
+
37
64
def visit_Compare (self , node ):
38
65
opstype = str (type (node .ops [0 ]))
39
66
if opstype in ["<class '_ast.Eq'>" ,"<class '_ast.NotEq'>" ,
@@ -59,11 +86,11 @@ def visit_Compare(self, node):
59
86
if self ._isStringClass (element ):
60
87
self .fullStrings .add (self ._getStringValue (element ))
61
88
62
- def visit_Call (self ,node ):
89
+ def visit_Call (self , node ):
63
90
try :
64
91
attr = node .func .attr
92
+ args = node .args
65
93
arg0 = node .args [0 ]
66
- string = node .args [0 ].s
67
94
except AttributeError :
68
95
# Call without attribute or first argument
69
96
# is not a regular string
@@ -72,10 +99,18 @@ def visit_Call(self,node):
72
99
# Call without arguments
73
100
return
74
101
75
- if attr == "startswith" and self ._isStringClass (arg0 ):
76
- self .prefixes .add (self ._getStringValue (arg0 ))
77
- elif attr == "endswith" and self ._isStringClass (arg0 ):
78
- self .suffixes .add (self ._getStringValue (arg0 ))
102
+ if attr == "startswith" :
103
+ for arg in node .args :
104
+ if self ._isStringClass (arg ):
105
+ self .prefixes .add (self ._getStringValue (arg ))
106
+ elif self ._isTupleClass (arg ):
107
+ self .prefixes .update (self ._getStringValuesAsList (arg ))
108
+ elif attr == "endswith" :
109
+ for arg in node .args :
110
+ if self ._isStringClass (arg ):
111
+ self .suffixes .add (self ._getStringValue (arg ))
112
+ elif self ._isTupleClass (arg ):
113
+ self .suffixes .update (self ._getStringValuesAsList (arg ))
79
114
elif attr == "index" and self ._isStringClass (arg0 ):
80
115
self .fragments .add (self ._getStringValue (arg0 ))
81
116
elif attr == "find" and self ._isStringClass (arg0 ):
0 commit comments