nodes: 0, module; 1, function_definition; 2, function_name:_item_attributes_match; 3, parameters; 4, comment:# type: (CryptoConfig, Dict, Dict) -> Bool; 5, block; 6, identifier:crypto_config; 7, identifier:plaintext_item; 8, identifier:encrypted_item; 9, expression_statement; 10, for_statement; 11, return_statement; 12, comment:"""Determines whether the unencrypted values in the plaintext items attributes are the same as those in the
      encrypted item. Essentially this uses brute force to cover when we don't know the primary and sort
      index attribute names, since they can't be encrypted.
  
      :param CryptoConfig crypto_config: CryptoConfig used in encrypting the given items
      :param dict plaintext_item: The plaintext item
      :param dict encrypted_item: The encrypted item
      :return: Bool response, True if the unencrypted attributes in the plaintext item match those in
      the encrypted item
      :rtype: bool
      """; 13, pattern_list; 14, call; 15, block; 16, True; 17, identifier:name; 18, identifier:value; 19, attribute; 20, argument_list; 21, if_statement; 22, if_statement; 23, identifier:plaintext_item; 24, identifier:items; 25, comparison_operator:crypto_config.attribute_actions.action(name) == CryptoAction.ENCRYPT_AND_SIGN; 26, block; 27, comparison_operator:encrypted_item.get(name) != value; 28, block; 29, call; 30, attribute; 31, continue_statement; 32, call; 33, identifier:value; 34, return_statement; 35, attribute; 36, argument_list; 37, identifier:CryptoAction; 38, identifier:ENCRYPT_AND_SIGN; 39, attribute; 40, argument_list; 41, False; 42, attribute; 43, identifier:action; 44, identifier:name; 45, identifier:encrypted_item; 46, identifier:get; 47, identifier:name; 48, identifier:crypto_config; 49, identifier:attribute_actions
code: def _item_attributes_match(crypto_config, plaintext_item, encrypted_item):
      # type: (CryptoConfig, Dict, Dict) -> Bool
      """Determines whether the unencrypted values in the plaintext items attributes are the same as those in the
      encrypted item. Essentially this uses brute force to cover when we don't know the primary and sort
      index attribute names, since they can't be encrypted.
  
      :param CryptoConfig crypto_config: CryptoConfig used in encrypting the given items
      :param dict plaintext_item: The plaintext item
      :param dict encrypted_item: The encrypted item
      :return: Bool response, True if the unencrypted attributes in the plaintext item match those in
      the encrypted item
      :rtype: bool
      """
  
      for name, value in plaintext_item.items():
          if crypto_config.attribute_actions.action(name) == CryptoAction.ENCRYPT_AND_SIGN:
              continue
  
          if encrypted_item.get(name) != value:
              return False
  
      return True