--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Security/SecurityUtils.py Tue Jun 09 20:10:59 2020 +0200 +++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Security/SecurityUtils.py Wed Jun 10 17:52:53 2020 +0200 @@ -258,3 +258,67 @@ @rtype bytes """ return b.decode('unicode_escape').encode('unicode_escape') + + +def concatString(node, stop=None): + """ + Function to build a string from an ast.BinOp chain. + + This will build a string from a series of ast.Str nodes wrapped in + ast.BinOp nodes. Something like "a" + "b" + "c" or "a %s" % val etc. + The provided node can be any participant in the BinOp chain. + + @param node node to be processed + @type ast.BinOp or ast.Str + @param stop base node to stop at + @type ast.BinOp or ast.Str + @return tuple containing the root node of the expression and the string + value + @rtype tuple of (ast.AST, str) + """ + def _get(node, bits, stop=None): + if node != stop: + bits.append( + _get(node.left, bits, stop) + if isinstance(node.left, ast.BinOp) + else node.left + ) + bits.append( + _get(node.right, bits, stop) + if isinstance(node.right, ast.BinOp) + else node.right + ) + + bits = [node] + while isinstance(node._securityParent, ast.BinOp): + node = node._securityParent + if isinstance(node, ast.BinOp): + _get(node, bits, stop) + + return ( + node, + " ".join([x.s for x in bits if isinstance(x, ast.Str)]) + ) + + +def getCalledName(node): + """ + Function to get the function name from an ast.Call node. + + An ast.Call node representing a method call will present differently to one + wrapping a function call: thing.call() vs call(). This helper will grab the + unqualified call name correctly in either case. + + @param node reference to the call node + @type ast.Call + @return function name of the node + @rtype str + """ + func = node.func + try: + return func.attr if isinstance(func, ast.Attribute) else func.id + except AttributeError: + return "" + +# +# eflag: noqa = M601