def filter(nodes): return [ node for node in nodes if (not (isinstance(node, ast.Expr) and isinstance(node.value, ast.Call)) or name_to_str(node.value.func) not in ignored_function_names) ]
def filter(body): nodes_to_unwrap = list(body) out = [] while nodes_to_unwrap: node = nodes_to_unwrap.pop(0) if isinstance(node, ast.With): matches = True for context_expr, optional_vars in with_to_items(node): if isinstance(context_expr, ast.Call): if name_to_str( context_expr.func) not in function_names: matches = False break else: matches = False break if matches: for child in reversed(node.body): nodes_to_unwrap.insert(0, child) else: out.append(node) else: out.append(node) return out
def compare_Call(self, n1, n2): # Allowed change no. 4 and 8 # Test if the function name has changed in one of the expected ways allowed_name_changes = ( ("read_bool", "serdes.bool"), ("read_nbits", "serdes.nbits"), ("read_uint_lit", "serdes.uint_lit"), ("read_uint_lit", "serdes.bytes"), ("read_uint", "serdes.uint"), ("read_uintb", "serdes.uint"), ("read_sint", "serdes.sint"), ("read_sintb", "serdes.sint"), ("byte_align", "serdes.byte_align"), ("flush_inputb", "serdes.bounded_block_end"), ) name1 = name_to_str(n1.func) name2 = name_to_str(n2.func) name_change_allowed = (name1, name2) in allowed_name_changes # Check the former function takes 'state' as its first argument n1_takes_state_as_first_arg = (len(n1.args) >= 1 and name_to_str(n1.args[0]) == "state") if name_change_allowed and n1_takes_state_as_first_arg: # Test if the arguments match (asside from an extra first argument # which will be 'state' in n1 and a target name in n2) return self.generic_compare( n1, n2, ignore_fields=["func"], # Ignores 'state' (in ref version) and 'serdes' (in impl. # version) filter_fields={"args": ignore_first_n(1)}, ) else: return self.generic_compare( n1, n2, # Allowed change no. 4 filter_fields={ "args": (None, ignore_leading_call_arguments("serdes")) }, )
def test_with_to_items(): with_items = [] class MyNV(ast.NodeVisitor): def visit_With(self, node): with_items.extend(with_to_items(node)) self.generic_visit(node) v = MyNV() v.visit(ast.parse("with foo() as bar, baz():\n pass")) assert len(with_items) == 2 assert isinstance(with_items[0][0], ast.Call) assert name_to_str(with_items[0][0].func) == "foo" assert isinstance(with_items[0][1], ast.Name) assert name_to_str(with_items[0][1]) == "bar" assert isinstance(with_items[1][0], ast.Call) assert name_to_str(with_items[1][0].func) == "baz" assert with_items[1][1] is None
def compare_Assign_Expr(self, n1, n2): # Allowed change no. 7 # n1 must assign to state['bits_left'] if len(n1.targets) != 1 or name_to_str( n1.targets[0]) != "state['bits_left']": return self.generic_compare(n1, n2) # n2 must contain a 'Call' to bounded_block_begin if (not isinstance(n2.value, ast.Call) or name_to_str(n2.value.func) != "serdes.bounded_block_begin"): return self.generic_compare(n1, n2) # n2 must have exactly one positional argument if (len(n2.value.args) != 1 or n2.value.keywords != [] or # Python 2.x only getattr(n2.value, "starargs", None) is not None or getattr(n2.value, "kwargs", None) is not None): return self.generic_compare(n1, n2) # n2's positional argument must exactly match the value assigned to # state['bits_left'] in the n1 return self.generic_compare(n1.value, n2.value.args[0])
def compare_Dict_Call(self, n1, n2): # Allowed change no. 9 is_empty_dict = len(n1.keys) == 0 and len(n1.values) == 0 is_empty_constructor = ( len(n2.args) == 0 and len(n2.keywords) == 0 and # Python 2.x getattr(n2, "starargs", None) is None and getattr(n2, "kwargs", None) is None) is_allowed_fixeddict = name_to_str(n2.func) in ( "State", "VideoParameters", ) if is_empty_dict and is_empty_constructor and is_allowed_fixeddict: return True else: return self.generic_compare(n1, n2)
def compare_Constant_Attribute(self, n1, n2): # Allowed change no. 3 # Resolve the constant used name_parts = name_to_str(n2).split(".") value = tables for part in name_parts: if hasattr(value, part): value = getattr(value, part) print(value) else: value = None break # Must be same value as the literal if n1.n == value: return True else: return self.generic_compare(n1, n2)
def test_unknown(self): # Just don't crash... value = ast.Num(123) assert isinstance(name_to_str(value), str)
def test_unsupported_subscript(self): # Just don't crash... value = ast.Name("foo", ast.Load) slice = ast.Index(ast.Name("bar", ast.Load)) subscript = ast.Subscript(value, slice, ast.Load) assert isinstance(name_to_str(subscript), str)
def test_num_subscript(self): value = ast.Name("foo", ast.Load) slice = ast.Index(ast.Num(123)) subscript = ast.Subscript(value, slice, ast.Load) assert name_to_str(subscript) == "foo[123]"
def test_str_subscript(self): value = ast.Name("foo", ast.Load) slice = ast.Index(ast.Str("bar")) subscript = ast.Subscript(value, slice, ast.Load) assert name_to_str(subscript) == "foo['bar']"
def test_attribute(self): value = ast.Name("foo", ast.Load) attr = ast.Attribute(value, "bar", ast.Load) assert name_to_str(attr) == "foo.bar"
def test_name(self): name = ast.Name("foo", ast.Load) assert name_to_str(name) == "foo"
def filter(decorator_list): return [ decorator for decorator in decorator_list if (name_to_str(decorator.func) if isinstance(decorator, ast.Call) else name_to_str(decorator)) not in ignored_decorator_names ]