nodes: 0, module; 1, function_definition; 2, function_name:canonical_ops; 3, parameters; 4, block; 5, identifier:ops; 6, expression_statement; 7, expression_statement; 8, return_statement; 9, string; 10, assignment; 11, identifier:new_ops; 12, string_content:Returns the given operations array sorted with duplicates removed.
  
      @param ops checker.Ops
      @return: checker.Ops; 13, identifier:new_ops; 14, call; 15, identifier:sorted; 16, argument_list; 17, call; 18, keyword_argument; 19, identifier:set; 20, argument_list; 21, identifier:key; 22, lambda; 23, identifier:ops; 24, lambda_parameters; 25, tuple; 26, identifier:x; 27, attribute; 28, attribute; 29, identifier:x; 30, identifier:entity; 31, identifier:x; 32, identifier:action
code: def canonical_ops(ops):
      ''' Returns the given operations array sorted with duplicates removed.
  
      @param ops checker.Ops
      @return: checker.Ops
      '''
      new_ops = sorted(set(ops), key=lambda x: (x.entity, x.action))
      return new_ops