+ def set_list(self, table, q_filter, update_dict):
+ """
+ Modifies al matching entries at database
+ :param table: collection or table
+ :param q_filter: Filter
+ :param update_dict: Plain dictionary with the content to be updated. It is a dot separated keys and a value
+ :return: Dict with the number of entries modified
+ """
+ raise DbException("Method 'set_list' not implemented")
+
+ def replace(self, table, _id, indata, fail_on_empty=True):
+ """
+ Replace the content of an entry
+ :param table: collection or table
+ :param _id: internal database id
+ :param indata: content to replace
+ :param fail_on_empty: If nothing matches filter it returns None unless this flag is set tu True, in which case
+ it raises a DbException
+ :return: Dict with the number of entries replaced
+ """
+ raise DbException("Method 'replace' not implemented")
+
+ @staticmethod
+ def _join_passwords(passwd_byte, passwd_str):
+ """
+ Modifies passwd_byte with the xor of passwd_str. Used for adding salt, join passwords, etc
+ :param passwd_byte: original password in bytes, 32 byte length
+ :param passwd_str: string salt to be added
+ :return: modified password in bytes
+ """
+ if not passwd_str:
+ return passwd_byte
+ secret_key = bytearray(passwd_byte)
+ for i, b in enumerate(passwd_str.encode()):
+ secret_key[i % 32] ^= b
+ return bytes(secret_key)
+
+ def set_secret_key(self, secret_key):
+ """
+ Set internal secret key used for encryption
+ :param secret_key: byte array length 32 with the secret_key
+ :return: None
+ """
+ assert (len(secret_key) == 32)
+ self.secret_key = self._join_passwords(secret_key, self.master_password)