docs: def decrypt_dynamodb_item(item, crypto_config):
      # type: (dynamodb_types.ITEM, CryptoConfig) -> dynamodb_types.ITEM
      """Decrypt a DynamoDB item.
  
      >>> from dynamodb_encryption_sdk.encrypted.item import decrypt_python_item
      >>> encrypted_item = {
      ...     'some': {'B': b'ENCRYPTED_DATA'},
      ...     'more': {'B': b'ENCRYPTED_DATA'}
      ... }
      >>> decrypted_item = decrypt_python_item(
      ...     item=encrypted_item,
      ...     crypto_config=my_crypto_config
      ... )
  
      .. note::
  
          This handles DynamoDB-formatted items and is for use with the boto3 DynamoDB client.
  
      :param dict item: Encrypted and signed DynamoDB item
      :param CryptoConfig crypto_config: Cryptographic configuration
      :returns: Plaintext DynamoDB item
      :rtype: dict
      """
      unique_actions = set([crypto_config.attribute_actions.default_action.name])
      unique_actions.update(set([action.name for action in crypto_config.attribute_actions.attribute_actions.values()]))
  
      if crypto_config.attribute_actions.take_no_actions:
          # If we explicitly have been told not to do anything to this item, just copy it.
          return item.copy()
  
      try:
          signature_attribute = item.pop(ReservedAttributes.SIGNATURE.value)
      except KeyError:
          # The signature is always written, so if no signature is found then the item was not
          # encrypted or signed.
          raise DecryptionError("No signature attribute found in item")
  
      inner_crypto_config = crypto_config.copy()
      # Retrieve the material description from the item if found.
      try:
          material_description_attribute = item.pop(ReservedAttributes.MATERIAL_DESCRIPTION.value)
      except KeyError:
          # If no material description is found, we use inner_crypto_config as-is.
          pass
      else:
          # If material description is found, override the material description in inner_crypto_config.
          material_description = deserialize_material_description(material_description_attribute)
          inner_crypto_config.encryption_context.material_description = material_description
  
      decryption_materials = inner_crypto_config.decryption_materials()
  
      verify_item_signature(signature_attribute, item, decryption_materials.verification_key, inner_crypto_config)
  
      try:
          decryption_key = decryption_materials.decryption_key
      except AttributeError:
          if inner_crypto_config.attribute_actions.contains_action(CryptoAction.ENCRYPT_AND_SIGN):
              raise DecryptionError(
                  "Attribute actions ask for some attributes to be decrypted but no decryption key is available"
              )
  
          return item.copy()
  
      decryption_mode = inner_crypto_config.encryption_context.material_description.get(
          MaterialDescriptionKeys.ATTRIBUTE_ENCRYPTION_MODE.value
      )
      algorithm_descriptor = decryption_key.algorithm + decryption_mode
  
      # Once the signature has been verified, actually decrypt the item attributes.
      decrypted_item = {}
      for name, attribute in item.items():
          if inner_crypto_config.attribute_actions.action(name) is CryptoAction.ENCRYPT_AND_SIGN:
              decrypted_item[name] = decrypt_attribute(
                  attribute_name=name, attribute=attribute, decryption_key=decryption_key, algorithm=algorithm_descriptor
              )
          else:
              decrypted_item[name] = attribute.copy()
  
      return decrypted_item