kdbxtool.database

High-level Database API for KDBX files.

This module provides the main interface for working with KeePass databases: - Opening and decrypting KDBX files - Creating new databases - Searching for entries and groups - Saving databases

Classes

CustomIcon(uuid, data[, name, ...])

A custom icon in a KDBX database.

Database(root_group[, settings, header, ...])

High-level interface for KDBX databases.

DatabaseSettings([generator, database_name, ...])

Settings for a KDBX database.

ProtectedStreamCipher(stream_id, stream_key)

Stream cipher for encrypting/decrypting protected values in XML.

class kdbxtool.database.ProtectedStreamCipher(stream_id, stream_key)[source]

Bases: object

Stream cipher for encrypting/decrypting protected values in XML.

KDBX uses a stream cipher (ChaCha20 or Salsa20) to protect sensitive values like passwords in the XML payload. Each protected value is XOR’d with the cipher output in document order.

Parameters:
__init__(stream_id, stream_key)[source]

Initialize the stream cipher.

Parameters:
  • stream_id (int) – Cipher type (2=Salsa20, 3=ChaCha20)

  • stream_key (bytes) – Key material from inner header (typically 64 bytes)

Return type:

None

decrypt(ciphertext)[source]

Decrypt protected value (XOR with stream).

Parameters:

ciphertext (bytes)

Return type:

bytes

encrypt(plaintext)[source]

Encrypt protected value (XOR with stream).

Parameters:

plaintext (bytes)

Return type:

bytes

class kdbxtool.database.CustomIcon(uuid, data, name=None, last_modification_time=None)[source]

Bases: object

A custom icon in a KDBX database.

Custom icons are PNG images that can be assigned to entries and groups for visual customization beyond the standard icon set.

Parameters:
uuid

Unique identifier for the icon

Type:

uuid.UUID

data

PNG image data

Type:

bytes

name

Optional display name for the icon

Type:

str | None

last_modification_time

When the icon was last modified

Type:

datetime.datetime | None

uuid: UUID
data: bytes
name: str | None = None
last_modification_time: datetime | None = None
__init__(uuid, data, name=None, last_modification_time=None)
Parameters:
Return type:

None

class kdbxtool.database.DatabaseSettings(generator='kdbxtool', database_name='Database', database_description='', default_username='', maintenance_history_days=365, color=None, master_key_change_rec=-1, master_key_change_force=-1, memory_protection=<factory>, recycle_bin_enabled=True, recycle_bin_uuid=None, history_max_items=10, history_max_size=6291456, custom_icons=<factory>, deleted_objects=<factory>)[source]

Bases: object

Settings for a KDBX database.

Parameters:
  • generator (str)

  • database_name (str)

  • database_description (str)

  • default_username (str)

  • maintenance_history_days (int)

  • color (str | None)

  • master_key_change_rec (int)

  • master_key_change_force (int)

  • memory_protection (dict[str, bool])

  • recycle_bin_enabled (bool)

  • recycle_bin_uuid (uuid_module.UUID | None)

  • history_max_items (int)

  • history_max_size (int)

  • custom_icons (dict[uuid_module.UUID, CustomIcon])

  • deleted_objects (list[DeletedObject])

generator

Generator application name

Type:

str

database_name

Name of the database

Type:

str

database_description

Description of the database

Type:

str

default_username

Default username for new entries

Type:

str

maintenance_history_days

Days to keep deleted items

Type:

int

color

Database color (hex)

Type:

str | None

master_key_change_rec

Days until master key change recommended

Type:

int

master_key_change_force

Days until master key change forced

Type:

int

memory_protection

Which fields to protect in memory

Type:

dict[str, bool]

recycle_bin_enabled

Whether recycle bin is enabled

Type:

bool

recycle_bin_uuid

UUID of recycle bin group

Type:

uuid_module.UUID | None

history_max_items

Max history entries per entry

Type:

int

history_max_size

Max history size in bytes

Type:

int

custom_icons

Dictionary of custom icons (UUID -> CustomIcon)

Type:

dict[uuid_module.UUID, CustomIcon]

generator: str = 'kdbxtool'
database_name: str = 'Database'
database_description: str = ''
default_username: str = ''
maintenance_history_days: int = 365
color: str | None = None
master_key_change_rec: int = -1
master_key_change_force: int = -1
memory_protection: dict[str, bool]
recycle_bin_enabled: bool = True
recycle_bin_uuid: uuid_module.UUID | None = None
history_max_items: int = 10
history_max_size: int = 6291456
custom_icons: dict[uuid_module.UUID, CustomIcon]
deleted_objects: list[DeletedObject]
__init__(generator='kdbxtool', database_name='Database', database_description='', default_username='', maintenance_history_days=365, color=None, master_key_change_rec=-1, master_key_change_force=-1, memory_protection=<factory>, recycle_bin_enabled=True, recycle_bin_uuid=None, history_max_items=10, history_max_size=6291456, custom_icons=<factory>, deleted_objects=<factory>)
Parameters:
  • generator (str)

  • database_name (str)

  • database_description (str)

  • default_username (str)

  • maintenance_history_days (int)

  • color (str | None)

  • master_key_change_rec (int)

  • master_key_change_force (int)

  • memory_protection (dict[str, bool])

  • recycle_bin_enabled (bool)

  • recycle_bin_uuid (uuid_module.UUID | None)

  • history_max_items (int)

  • history_max_size (int)

  • custom_icons (dict[uuid_module.UUID, CustomIcon])

  • deleted_objects (list[DeletedObject])

Return type:

None

class kdbxtool.database.Database(root_group, settings=None, header=None, inner_header=None, binaries=None)[source]

Bases: object

High-level interface for KDBX databases.

This class provides the main API for working with KeePass databases. It handles encryption/decryption, XML parsing, and model management.

Example usage:

# Open existing database db = Database.open(“passwords.kdbx”, password=”secret”)

# Find entries entries = db.find_entries(title=”GitHub”)

# Create entry entry = db.root_group.create_entry(

title=”New Site”, username=”user”, password=”pass123”,

)

# Save changes db.save()

Parameters:
__init__(root_group, settings=None, header=None, inner_header=None, binaries=None)[source]

Initialize database.

Usually you should use Database.open() or Database.create() instead.

Parameters:
  • root_group (Group) – Root group containing all entries/groups

  • settings (DatabaseSettings | None) – Database settings

  • header (KdbxHeader | None) – KDBX header (for existing databases)

  • inner_header (InnerHeader | None) – Inner header (for existing databases)

  • binaries (dict[int, bytes] | None) – Binary attachments

Return type:

None

zeroize_credentials()[source]

Explicitly zeroize stored credentials from memory.

Call this when done with the database to minimize the time credentials remain in memory. Note that Python’s string interning may retain copies; for maximum security, use SecureBytes for credential input.

Return type:

None

dump()[source]

Return a human-readable summary of the database for debugging.

Returns:

Multi-line string with database metadata and statistics.

Return type:

str

merge(source, *, mode=None)[source]

Merge another database into this one.

Combines entries, groups, history, attachments, and custom icons from the source database into this database using UUID-based matching and timestamp-based conflict resolution.

Parameters:
  • source (Database) – Database to merge from (read-only)

  • mode (MergeMode | None) – Merge mode (STANDARD or SYNCHRONIZE). Defaults to STANDARD. - STANDARD: Add and update only, never deletes - SYNCHRONIZE: Full sync including deletions

Returns:

MergeResult with counts and statistics about the merge

Raises:

MergeError – If merge cannot be completed

Return type:

MergeResult

Example

>>> target_db = Database.open("main.kdbx", password="secret")
>>> source_db = Database.open("branch.kdbx", password="secret")
>>> result = target_db.merge(source_db)
>>> print(f"Added {result.entries_added} entries")
>>> target_db.save()
property transformed_key: bytes | None

Get the transformed key for caching.

The transformed key is the result of applying the KDF (Argon2) to the credentials. Caching this allows fast repeated database opens without re-running the expensive KDF.

Security note: The transformed key is as sensitive as the password. Anyone with this key can decrypt the database. Store securely and zeroize when done.

Returns:

The transformed key, or None if not available (e.g., newly created DB)

property kdf_salt: bytes | None

Get the KDF salt used for key derivation.

The salt is used together with credentials to derive the transformed key. If the salt changes (e.g., after save with regenerate_seeds=True), any cached transformed_key becomes invalid.

Returns:

The KDF salt, or None if no header is set

property root_group: Group

Get the root group of the database.

property settings: DatabaseSettings

Get database settings.

property filepath: Path | None

Get the file path (if opened from file).

classmethod open(filepath, password=None, keyfile=None, yubikey_slot=None, yubikey_serial=None)[source]

Open an existing KDBX database.

Parameters:
  • filepath (str | Path) – Path to the .kdbx file

  • password (str | None) – Database password

  • keyfile (str | Path | None) – Path to keyfile (optional)

  • yubikey_slot (int | None) – YubiKey slot for challenge-response (1 or 2, optional). If provided, the database’s KDF salt is used as challenge and the 20-byte HMAC-SHA1 response is incorporated into key derivation. Requires yubikey-manager package: pip install kdbxtool[yubikey]

  • yubikey_serial (int | None) – Serial number of specific YubiKey to use when multiple devices are connected. Use list_yubikeys() to discover serials.

Returns:

Database instance

Raises:
Return type:

Database

classmethod open_interactive(filepath, keyfile=None, yubikey_slot=None, yubikey_serial=None, prompt='Password: ', max_attempts=3)[source]

Open a KDBX database with interactive password prompt.

Prompts the user for a password using secure input (no echo). If the password is incorrect, allows retrying up to max_attempts times.

This is a convenience method for CLI applications that need to securely prompt for database credentials.

Parameters:
  • filepath (str | Path) – Path to the .kdbx file

  • keyfile (str | Path | None) – Path to keyfile (optional)

  • yubikey_slot (int | None) – YubiKey slot for challenge-response (1 or 2, optional)

  • yubikey_serial (int | None) – Serial number of specific YubiKey to use

  • prompt (str) – Custom prompt string (default: “Password: “)

  • max_attempts (int) – Maximum password attempts before raising (default: 3)

Returns:

Database instance

Raises:
Return type:

Database

Example

>>> db = Database.open_interactive("vault.kdbx")
Password:
>>> db = Database.open_interactive("vault.kdbx", keyfile="vault.key")
Password:
classmethod open_bytes(data, password=None, keyfile_data=None, filepath=None, transformed_key=None, yubikey_slot=None, yubikey_serial=None)[source]

Open a KDBX database from bytes.

Supports both KDBX3 and KDBX4 formats. KDBX3 databases are opened read-only and will be automatically upgraded to KDBX4 on save.

Parameters:
  • data (bytes) – KDBX file contents

  • password (str | None) – Database password

  • keyfile_data (bytes | None) – Keyfile contents (optional)

  • filepath (Path | None) – Original file path (for save)

  • transformed_key (bytes | None) – Precomputed transformed key (skips KDF, faster opens)

  • yubikey_slot (int | None) – YubiKey slot for challenge-response (1 or 2, optional). If provided, the database’s KDF salt is used as challenge and the 20-byte HMAC-SHA1 response is incorporated into key derivation. Requires yubikey-manager package: pip install kdbxtool[yubikey]

  • yubikey_serial (int | None) – Serial number of specific YubiKey to use when multiple devices are connected. Use list_yubikeys() to discover serials.

Returns:

Database instance

Raises:

YubiKeyError – If YubiKey operation fails

Return type:

Database

classmethod create(filepath=None, password=None, keyfile=None, database_name='Database', cipher=Cipher.AES256_CBC, kdf_config=None)[source]

Create a new KDBX database.

Parameters:
  • filepath (str | Path | None) – Path to save the database (optional)

  • password (str | None) – Database password

  • keyfile (str | Path | None) – Path to keyfile (optional)

  • database_name (str) – Name for the database

  • cipher (Cipher) – Encryption cipher to use

  • kdf_config (Argon2Config | AesKdfConfig | None) – KDF configuration (Argon2Config or AesKdfConfig). Defaults to Argon2Config.standard() with Argon2d variant.

Returns:

New Database instance

Return type:

Database

save(filepath=None, *, allow_upgrade=False, regenerate_seeds=True, kdf_config=None, cipher=None, yubikey_slot=None, yubikey_serial=None)[source]

Save the database to a file.

KDBX3 databases are automatically upgraded to KDBX4 on save. When saving a KDBX3 database to its original file, explicit confirmation is required via the allow_upgrade parameter.

Parameters:
  • filepath (str | Path | None) – Path to save to (uses original path if not specified)

  • allow_upgrade (bool) – Must be True to confirm KDBX3 to KDBX4 upgrade when saving to the original file. Not required when saving to a new file.

  • regenerate_seeds (bool) – If True (default), regenerate all cryptographic seeds (master_seed, encryption_iv, kdf_salt, random_stream_key) on save. Set to False only for testing or when using pre-computed transformed keys.

  • kdf_config (Argon2Config | AesKdfConfig | None) – Optional KDF configuration for KDBX3 upgrade. Use presets like: - Argon2Config.standard() / high_security() / fast() - AesKdfConfig.standard() / high_security() / fast() Defaults to Argon2Config.standard() with Argon2d variant.

  • cipher (Cipher | None) – Optional encryption cipher. Use one of: - Cipher.AES256_CBC (default, widely compatible) - Cipher.CHACHA20 (modern, faster in software) - Cipher.TWOFISH256_CBC (requires oxifish package) If not specified, preserves existing cipher.

  • yubikey_slot (int | None) – YubiKey slot for challenge-response (1 or 2, optional). If provided (or if database was opened with yubikey_slot), the new KDF salt is used as challenge and the response is incorporated into key derivation. Requires yubikey-manager package.

  • yubikey_serial (int | None) – Serial number of specific YubiKey to use when multiple devices are connected. Use list_yubikeys() to discover serials.

Raises:
Return type:

None

reload()[source]

Reload the database from disk using stored credentials.

Re-reads the database file and replaces all in-memory state with the current file contents. Useful for discarding unsaved changes or syncing with external modifications.

Raises:
Return type:

None

xml(*, pretty_print=False)[source]

Export database XML payload.

Returns the decrypted, decompressed XML payload of the database. Protected values (passwords, etc.) are shown in plaintext. Useful for debugging and migration.

Parameters:

pretty_print (bool) – If True, format XML with indentation for readability

Returns:

XML payload as bytes (UTF-8 encoded)

Return type:

bytes

dump_xml(filepath, *, pretty_print=True)[source]

Write database XML payload to a file.

Writes the decrypted, decompressed XML payload to a file. Protected values (passwords, etc.) are shown in plaintext. Useful for debugging and migration.

Parameters:
  • filepath (str | Path) – Path to write the XML file

  • pretty_print (bool) – If True (default), format XML with indentation

Return type:

None

to_bytes(*, regenerate_seeds=True, kdf_config=None, cipher=None, yubikey_slot=None, yubikey_serial=None)[source]

Serialize the database to KDBX4 format.

KDBX3 databases are automatically upgraded to KDBX4 on save. This includes converting to the specified KDF and ChaCha20 protected stream.

Parameters:
  • regenerate_seeds (bool) – If True (default), regenerate all cryptographic seeds (master_seed, encryption_iv, kdf_salt, random_stream_key) on save. This prevents precomputation attacks where an attacker can derive the encryption key in advance. Set to False only for testing or when using pre-computed transformed keys.

  • kdf_config (Argon2Config | AesKdfConfig | None) – Optional KDF configuration for KDBX3 upgrade. Use presets like: - Argon2Config.standard() / high_security() / fast() - AesKdfConfig.standard() / high_security() / fast() Defaults to Argon2Config.standard() with Argon2d variant.

  • cipher (Cipher | None) – Optional encryption cipher. Use one of: - Cipher.AES256_CBC (default, widely compatible) - Cipher.CHACHA20 (modern, faster in software) - Cipher.TWOFISH256_CBC (requires oxifish package) If not specified, preserves existing cipher.

  • yubikey_slot (int | None) – YubiKey slot for challenge-response (1 or 2, optional). If provided, the (new) KDF salt is used as challenge and the 20-byte HMAC-SHA1 response is incorporated into key derivation. Requires yubikey-manager package: pip install kdbxtool[yubikey]

  • yubikey_serial (int | None) – Serial number of specific YubiKey to use when multiple devices are connected. Use list_yubikeys() to discover serials.

Returns:

KDBX4 file contents as bytes

Raises:
Return type:

bytes

set_credentials(password=None, keyfile_data=None)[source]

Set or update database credentials.

Parameters:
  • password (str | None) – New password (None to remove)

  • keyfile_data (bytes | None) – New keyfile data (None to remove)

Raises:

ValueError – If both password and keyfile are None

Return type:

None

find_entries(title=None, username=None, password=None, url=None, notes=None, otp=None, tags=None, string=None, autotype_enabled=None, autotype_sequence=None, autotype_window=None, uuid=None, path=None, recursive=True, history=False, first=False)[source]

Find entries matching criteria.

Parameters:
  • title (str | None) – Match entries with this title

  • username (str | None) – Match entries with this username

  • password (str | None) – Match entries with this password

  • url (str | None) – Match entries with this URL

  • notes (str | None) – Match entries with these notes

  • otp (str | None) – Match entries with this OTP

  • tags (list[str] | None) – Match entries with all these tags

  • string (dict[str, str] | None) – Match entries with custom properties (dict of key:value)

  • autotype_enabled (bool | None) – Filter by AutoType enabled state

  • autotype_sequence (str | None) – Match entries with this AutoType sequence

  • autotype_window (str | None) – Match entries with this AutoType window

  • uuid (UUID | None) – Match entry with this UUID

  • path (list[str] | str | None) – Path to entry as list of group names ending with entry title, or as a ‘/’-separated string. When specified, other criteria are ignored.

  • recursive (bool) – Search in subgroups

  • history (bool) – Include history entries in search

  • first (bool) – If True, return first match or None. If False, return list.

Returns:

Entry or None If first=False: List of matching entries

Return type:

If first=True

find_groups(name=None, uuid=None, path=None, recursive=True, first=False)[source]

Find groups matching criteria.

Parameters:
  • name (str | None) – Match groups with this name

  • uuid (UUID | None) – Match group with this UUID

  • path (list[str] | str | None) – Path to group as list of group names or as a ‘/’-separated string. When specified, other criteria are ignored.

  • recursive (bool) – Search in nested subgroups

  • first (bool) – If True, return first matching group or None instead of list

Returns:

List of matching groups, or single Group/None if first=True

Return type:

list[Group] | Group | None

find_entries_contains(title=None, username=None, password=None, url=None, notes=None, otp=None, recursive=True, case_sensitive=False, history=False)[source]

Find entries where fields contain the given substrings.

All criteria are combined with AND logic. None means “any value”.

Parameters:
  • title (str | None) – Match entries whose title contains this substring

  • username (str | None) – Match entries whose username contains this substring

  • password (str | None) – Match entries whose password contains this substring

  • url (str | None) – Match entries whose URL contains this substring

  • notes (str | None) – Match entries whose notes contain this substring

  • otp (str | None) – Match entries whose OTP contains this substring

  • recursive (bool) – Search in subgroups

  • case_sensitive (bool) – If False (default), matching is case-insensitive

  • history (bool) – Include history entries in search

Returns:

List of matching entries

Return type:

list[Entry]

find_entries_regex(title=None, username=None, password=None, url=None, notes=None, otp=None, recursive=True, case_sensitive=False, history=False)[source]

Find entries where fields match the given regex patterns.

All criteria are combined with AND logic. None means “any value”.

Parameters:
  • title (str | None) – Regex pattern to match against title

  • username (str | None) – Regex pattern to match against username

  • password (str | None) – Regex pattern to match against password

  • url (str | None) – Regex pattern to match against URL

  • notes (str | None) – Regex pattern to match against notes

  • otp (str | None) – Regex pattern to match against OTP

  • recursive (bool) – Search in subgroups

  • case_sensitive (bool) – If False (default), matching is case-insensitive

  • history (bool) – Include history entries in search

Returns:

List of matching entries

Raises:

re.error – If any pattern is not a valid regex

Return type:

list[Entry]

find_attachments(id=None, filename=None, regex=False, recursive=True, history=False, first=False)[source]

Find attachments in the database.

Parameters:
  • id (int | None) – Match attachments with this binary reference ID

  • filename (str | None) – Match attachments with this filename (exact or regex)

  • regex (bool) – If True, treat filename as a regex pattern

  • recursive (bool) – Search in subgroups

  • history (bool) – Include history entries in search

  • first (bool) – If True, return first match or None. If False, return list.

Returns:

Attachment or None If first=False: List of matching attachments

Return type:

If first=True

property attachments: list[Attachment]

Get all attachments in the database.

iter_entries(recursive=True)[source]

Iterate over all entries in the database.

Parameters:

recursive (bool) – Include entries from all subgroups

Yields:

Entry objects

Return type:

Iterator[Entry]

iter_groups(recursive=True)[source]

Iterate over all groups in the database.

Parameters:

recursive (bool) – Include nested subgroups

Yields:

Group objects

Return type:

Iterator[Group]

deref(value)[source]

Resolve KeePass field references in a value.

Parses field references in the format {REF:X@Y:Z} and replaces them with the actual values from the referenced entries: - X = Field to retrieve (T=Title, U=Username, P=Password, A=URL, N=Notes, I=UUID) - Y = Field to search by (T, U, P, A, N, I) - Z = Search value

References are resolved recursively, so a reference that resolves to another reference will continue resolving until a final value is found.

Parameters:

value (str | None) – String potentially containing field references

Returns:

  • The resolved string with all references replaced

  • A UUID if the final result is a UUID reference

  • None if any referenced entry cannot be found

  • The original value if it contains no references or is None

Return type:

str | UUID | None

Example

>>> # Entry with password = '{REF:P@I:ABCD1234...}'
>>> db.deref(entry.password)  # Returns the referenced password
>>>
>>> # With prefix/suffix: 'prefix{REF:U@I:...}suffix'
>>> db.deref(value)  # Returns 'prefix<username>suffix'
move_entry(entry, destination)[source]

Move an entry to a different group.

This is a convenience method that calls entry.move_to(). It validates that both the entry and destination belong to this database.

Parameters:
  • entry (Entry) – Entry to move

  • destination (Group) – Target group to move the entry to

Raises:
  • ValueError – If entry or destination is not in this database

  • ValueError – If entry has no parent

  • ValueError – If destination is the current parent

Return type:

None

move_group(group, destination)[source]

Move a group to a different parent group.

This is a convenience method that calls group.move_to(). It validates that both the group and destination belong to this database.

Parameters:
  • group (Group) – Group to move

  • destination (Group) – Target parent group to move the group to

Raises:
  • ValueError – If group or destination is not in this database

  • ValueError – If group is the root group

  • ValueError – If group has no parent

  • ValueError – If destination is the current parent

  • ValueError – If destination is the group itself or a descendant

Return type:

None

property recyclebin_group: Group | None

Get the recycle bin group, or None if disabled.

If recycle_bin_enabled is True but no recycle bin exists yet, this creates one automatically.

Returns:

Recycle bin Group, or None if recycle bin is disabled

trash_entry(entry)[source]

Move an entry to the recycle bin.

If the entry is already in the recycle bin, it is permanently deleted.

Parameters:

entry (Entry) – Entry to trash

Raises:
Return type:

None

trash_group(group)[source]

Move a group to the recycle bin.

If the group is already in the recycle bin, it is permanently deleted. Cannot trash the root group or the recycle bin itself.

Parameters:

group (Group) – Group to trash

Raises:
Return type:

None

empty_group(group)[source]

Delete all entries and subgroups from a group.

This permanently deletes all contents (does not use recycle bin). The group itself is not deleted.

Parameters:

group (Group) – Group to empty

Raises:

ValueError – If group is not in this database

Return type:

None

apply_protection_policy(entry)[source]

Apply the database’s memory protection policy to an entry.

Updates the protected flag on the entry’s string fields according to the database’s memory_protection settings.

This is automatically applied when saving the database, but can be called manually if you need protection applied immediately for in-memory operations.

Parameters:

entry (Entry) – Entry to apply policy to

Return type:

None

apply_protection_policy_all()[source]

Apply memory protection policy to all entries in the database.

Updates all entries’ string field protection flags according to the database’s memory_protection settings.

Return type:

None

get_binary(ref)[source]

Get binary attachment data by reference ID.

Parameters:

ref (int) – Binary reference ID

Returns:

Binary data or None if not found

Return type:

bytes | None

add_binary(data, protected=True)[source]

Add a new binary attachment to the database.

Parameters:
  • data (bytes) – Binary data

  • protected (bool) – Whether the binary should be memory-protected

Returns:

Reference ID for the new binary

Return type:

int

remove_binary(ref)[source]

Remove a binary attachment from the database.

Parameters:

ref (int) – Binary reference ID

Returns:

True if removed, False if not found

Return type:

bool

get_attachment(entry, name)[source]

Get an attachment from an entry by filename.

Parameters:
  • entry (Entry) – Entry to get attachment from

  • name (str) – Filename of the attachment

Returns:

Attachment data or None if not found

Return type:

bytes | None

add_attachment(entry, name, data, protected=True)[source]

Add an attachment to an entry.

Parameters:
  • entry (Entry) – Entry to add attachment to

  • name (str) – Filename for the attachment

  • data (bytes) – Attachment data

  • protected (bool) – Whether the attachment should be memory-protected

Return type:

None

remove_attachment(entry, name)[source]

Remove an attachment from an entry by filename.

Parameters:
  • entry (Entry) – Entry to remove attachment from

  • name (str) – Filename of the attachment

Returns:

True if removed, False if not found

Return type:

bool

list_attachments(entry)[source]

List all attachment filenames for an entry.

Parameters:

entry (Entry) – Entry to list attachments for

Returns:

List of attachment filenames

Return type:

list[str]

property custom_icons: dict[UUID, CustomIcon]

Get dictionary of custom icons (UUID -> CustomIcon).

get_custom_icon(uuid)[source]

Get custom icon data by UUID.

Parameters:

uuid (UUID) – UUID of the custom icon

Returns:

PNG image data, or None if not found

Return type:

bytes | None

add_custom_icon(data, name=None)[source]

Add a custom icon to the database.

Parameters:
  • data (bytes) – PNG image data

  • name (str | None) – Optional display name for the icon

Returns:

UUID of the new custom icon

Return type:

UUID

remove_custom_icon(uuid)[source]

Remove a custom icon from the database.

Note: This does not update entries/groups that reference this icon. They will continue to reference the now-missing UUID.

Parameters:

uuid (UUID) – UUID of the custom icon to remove

Returns:

True if removed, False if not found

Return type:

bool

find_custom_icon_by_name(name)[source]

Find a custom icon by name.

Parameters:

name (str) – Name of the icon to find (must match exactly one icon)

Returns:

UUID of the matching icon, or None if not found

Raises:

ValueError – If multiple icons have the same name

Return type:

UUID | None