Skip to content

kaptive.db.manager

Database management module for downloading, compiling, and managing Kaptive databases.

This module defines the DatabaseManager class, which acts as the core controller for managing Kaptive surface antigen database assets both locally and remotely.

Databases are curated as source GenBank (.gbk) and metadata (.toml) files in remote GitHub repositories. DatabaseManager handles remote retrieval over HTTP, version evaluation via DatabaseMetadata, on-the-fly parsing and compilation into optimized Database instances, local caching in ~/.kaptive, fast disk serialization (pickling), and lifecycle commands (install, update, uninstall, reset, add, load, save).

Classes:

  • DatabaseManager –

    Class managing local database storage and remote GitHub database retrieval.

DatabaseManager

Class for managing Kaptive databases both on the user's disk and in curator GitHub repositories.

This class provides a comprehensive mechanism for downloading, compiling, and managing Kaptive databases. Databases are maintained as source files (GenBank and TOML) in Git repositories. The DatabaseManager fetches these files, compiles them into optimized, flat Database objects (using a Structure-of-Arrays layout for vectorized operations), and stores them locally as serialized pickle files (.pkl) alongside .json metadata sidecars in the user's local directory (defaults to ~/.kaptive or $KAPTIVE_DB_DIR).

The manager handles:

  • Installation: Fetching a known database from its remote repository (install), or a custom database from any GitHub repository (add), compiling it, and caching the result locally.
  • Updates: Checking the local compiled database against the remote repository's version (specified in the TOML metadata) and downloading/recompiling if a newer version exists (update).
  • Storage & Retrieval: Saving (save) and loading (load) these compiled .pkl files efficiently.
  • Lifecycle Management: Uninstalling specific databases (uninstall) or completely resetting the local cache (reset).

Attributes:

  • _KNOWN (dict[str, tuple[str, str, str]]) –

    Internal lookup mapping of officially supported database keywords to tuples of (repository_owner, repository_name, database_base_name).

  • _DB_DIR (Path) –

    Local cache directory path where .pkl database files and .json metadata sidecars are stored.

Methods:

  • add –

    Add or update a database directly from a specified remote Git repository.

  • get –

    Load a Database from a file path or resolve and load it by keyword.

  • install –

    Install known, officially supported databases by keyword.

  • installed –

    Return a list of keywords for all currently installed databases.

  • known –

    Return a list of keywords for all currently known, officially supported databases.

  • load –

    Load a locally installed, compiled database using its keyword.

  • reset –

    Remove all installed databases by deleting their compiled files from the local directory.

  • save –

    Serialize and save a compiled Database object and its metadata to local storage.

  • uninstall –

    Uninstall a specific database by removing its compiled local .pkl and .json files.

  • update –

    Update installed databases by checking against their remote GitHub repositories.

add classmethod

add(owner: str, repo_name: str, db_name: str, branch: str = 'main', local_meta: DatabaseMetadata | None = None) -> Database | None

Add or update a database directly from a specified remote Git repository.

This is the primary method for adding custom or official databases from GitHub. The procedure:

  1. Constructs raw GitHub URL endpoints for the repository's .toml metadata and .gbk GenBank files.
  2. Downloads and parses the remote TOML metadata to extract version information.
  3. Compares the remote version against local metadata (if available). If up-to-date, skips remaining steps and returns None.
  4. Downloads the raw GenBank file content over HTTP.
  5. Writes source files into a temporary directory and compiles them using from_genbank.
  6. Serializes and caches the compiled Database object into the local storage directory.

Parameters:

  • owner

    (str) –

    Owner or organization of the GitHub repository (e.g., 'klebgenomics').

  • repo_name

    (str) –

    Name of the GitHub repository (e.g., 'KpSC_surface_antigen_loci').

  • db_name

    (str) –

    Base name of the database files in the repository (e.g., 'Klebsiella_pneumoniae_Species_Complex_K').

  • branch

    (str, default: 'main' ) –

    Git branch name to fetch from. Defaults to 'main'.

  • local_meta

    (DatabaseMetadata | None, default: None ) –

    Pre-loaded metadata of local database installation. Defaults to None.

Returns:

  • Database | None –

    Database | None: The newly compiled Database object if installed or updated, or None if the local version was already up-to-date.

Raises:

  • DatabaseError –

    If repository files are not found, network issues occur, or file compilation fails.

See Also

DatabaseManager, Database, DatabaseMetadata, DatabaseError

Source code in src/kaptive/db/manager.py
@classmethod
def add(
    cls,
    owner: str,
    repo_name: str,
    db_name: str,
    branch: str = "main",
    local_meta: DatabaseMetadata | None = None,
) -> Database | None:
    r"""Add or update a database directly from a specified remote Git repository.

    This is the primary method for adding custom or official databases from GitHub. The procedure:

    1. Constructs raw GitHub URL endpoints for the repository's `.toml` metadata and `.gbk` GenBank files.
    2. Downloads and parses the remote TOML metadata to extract version information.
    3. Compares the remote version against local metadata (if available). If up-to-date, skips remaining steps and
       returns `None`.
    4. Downloads the raw GenBank file content over HTTP.
    5. Writes source files into a temporary directory and compiles them using
       [`from_genbank`][kaptive.db.core.Database.from_genbank].
    6. Serializes and caches the compiled [`Database`][kaptive.db.core.Database] object into the local storage
       directory.

    Args:
        owner (str): Owner or organization of the GitHub repository (e.g., `'klebgenomics'`).
        repo_name (str): Name of the GitHub repository (e.g., `'KpSC_surface_antigen_loci'`).
        db_name (str): Base name of the database files in the repository
            (e.g., `'Klebsiella_pneumoniae_Species_Complex_K'`).
        branch (str): Git branch name to fetch from. Defaults to `'main'`.
        local_meta (DatabaseMetadata | None): Pre-loaded metadata of local database installation.
            Defaults to `None`.

    Returns:
        Database | None: The newly compiled [`Database`][kaptive.db.core.Database] object if installed or updated,
            or `None` if the local version was already up-to-date.

    Raises:
        DatabaseError: If repository files are not found, network issues occur, or file compilation fails.

    See Also:
        [`DatabaseManager`][kaptive.db.manager.DatabaseManager],
        [`Database`][kaptive.db.core.Database],
        [`DatabaseMetadata`][kaptive.db.models.DatabaseMetadata],
        [`DatabaseError`][kaptive.db.models.DatabaseError]
    """
    fetched = cls._fetch_files(owner, repo_name, db_name, branch=branch, local_meta=local_meta)
    if fetched is None:
        return None
    return cls._compile_and_save(*fetched)

get classmethod

Load a Database from a file path or resolve and load it by keyword.

If file_or_keyword points to an existing file, it is loaded directly. Otherwise, it is treated as a keyword. If the keyword is not installed locally, it will be automatically downloaded and installed.

Parameters:

  • file_or_keyword

    (str | Path) –

    File path or recognized database keyword.

Returns:

Source code in src/kaptive/db/manager.py
@classmethod
def get(cls, file_or_keyword: str | Path) -> Database:
    r"""Load a Database from a file path or resolve and load it by keyword.

    If `file_or_keyword` points to an existing file, it is loaded directly.
    Otherwise, it is treated as a keyword. If the keyword is not installed locally,
    it will be automatically downloaded and installed.

    Args:
        file_or_keyword (str | Path): File path or recognized database keyword.

    Returns:
        Database: The loaded [`Database`][kaptive.db.core.Database] instance.
    """
    from kaptive.db.core import Database

    try:
        file_path = Path(file_or_keyword)
        if file_path.is_file():
            return Database.load(file_path)
    except (TypeError, ValueError, OSError):
        pass

    try:
        return cls.load(str(file_or_keyword))
    except DatabaseError:
        result = cls.install(str(file_or_keyword))
        if isinstance(result, list):
            result = result[0]
        if result is None:
            return cls.load(str(file_or_keyword))
        return result

install classmethod

install(kwd: str | list[str]) -> Database | list[Database | None]

Install known, officially supported databases by keyword.

Looks up the repository details (owner, repo, database name) associated with the provided keyword(s) in the internal registry (_KNOWN) and delegates file retrieval and compilation to add. If 'all' or a list of keywords is supplied, fetching is performed concurrently via a thread pool executor.

Parameters:

  • kwd

    (str | list[str]) –

    The keyword(s) of the known database(s) to install (e.g., 'kpsc_k', ['kpsc_k', 'ab_k'], or 'all').

Returns:

  • Database | list[Database | None] –

    Database | list[Database | None]: For a single keyword, returns the compiled Database object (or None if already up-to-date). For a list of keywords or 'all', returns a list of compiled Database objects (or None for entries that were up-to-date).

Raises:

  • DatabaseError –

    If any keyword is not recognized in the list of known databases, or if network/parsing errors occur.

See Also

known, DatabaseManager, add, Database, DatabaseError

Source code in src/kaptive/db/manager.py
@classmethod
def install(cls, kwd: str | list[str]) -> Database | list[Database | None]:
    r"""Install known, officially supported databases by keyword.

    Looks up the repository details (owner, repo, database name) associated with the provided keyword(s)
    in the internal registry (`_KNOWN`) and delegates file retrieval
    and compilation to [`add`][kaptive.db.manager.DatabaseManager.add]. If `'all'` or a list of keywords is
    supplied, fetching is performed concurrently via a thread pool executor.

    Args:
        kwd (str | list[str]): The keyword(s) of the known database(s) to install (e.g., `'kpsc_k'`,
            `['kpsc_k', 'ab_k']`, or `'all'`).

    Returns:
        Database | list[Database | None]: For a single keyword, returns the compiled
            [`Database`][kaptive.db.core.Database] object (or `None` if already up-to-date). For a list of
            keywords or `'all'`, returns a list of compiled [`Database`][kaptive.db.core.Database] objects
            (or `None` for entries that were up-to-date).

    Raises:
        DatabaseError: If any keyword is not recognized in the list of known databases, or if network/parsing
            errors occur.

    See Also:
        [`known`][kaptive.db.manager.DatabaseManager.known],
        [`DatabaseManager`][kaptive.db.manager.DatabaseManager],
        [`add`][kaptive.db.manager.DatabaseManager.add],
        [`Database`][kaptive.db.core.Database],
        [`DatabaseError`][kaptive.db.models.DatabaseError]
    """
    if kwd == "all":
        kwd = list(cls._KNOWN.keys())

    if isinstance(kwd, list):

        def _fetch_one(k: str):
            if (known_info := cls._KNOWN.get(k, None)) is None:
                raise DatabaseError(f'"{k}" is not a known database, choose from {list(cls._KNOWN.keys())}')
            return cls._fetch_files(*known_info)

        with concurrent.futures.ThreadPoolExecutor() as executor:
            fetched_list = list(executor.map(_fetch_one, kwd))

        results = []
        for fetched in fetched_list:
            if fetched is None:
                results.append(None)
            else:
                results.append(cls._compile_and_save(*fetched))
        return results

    if (known_info := cls._KNOWN.get(kwd, None)) is None:
        raise DatabaseError(f'"{kwd}" is not a known database, choose from {list(cls._KNOWN.keys())}')
    return cls.add(*known_info)  # type: ignore

installed classmethod

installed() -> list[str]

Return a list of keywords for all currently installed databases.

Scans the local storage directory for .pkl files and extracts their keywords from the file stems.

Returns:

  • list[str] –

    list[str]: A list of database keywords corresponding to installed .pkl database files. Returns an empty list if no databases are installed or if the storage directory does not exist.

See Also

DatabaseManager, known

Source code in src/kaptive/db/manager.py
@classmethod
def installed(cls) -> list[str]:
    r"""Return a list of keywords for all currently installed databases.

    Scans the local storage directory for `.pkl` files and extracts their keywords from the file stems.

    Returns:
        list[str]: A list of database keywords corresponding to installed `.pkl` database files.
            Returns an empty list if no databases are installed or if the storage directory does not exist.

    See Also:
        [`DatabaseManager`][kaptive.db.manager.DatabaseManager],
        [`known`][kaptive.db.manager.DatabaseManager.known]
    """
    if not cls._DB_DIR.exists():
        return []
    return [p.stem for p in cls._DB_DIR.glob("*.pkl")]

known classmethod

known() -> list[str]

Return a list of keywords for all currently known, officially supported databases.

These databases can be installed directly by providing their keyword to install.

Returns:

  • list[str] –

    list[str]: A list of known database keywords (e.g., ['kpsc_k', 'kpsc_o', 'kosc_k', ...]).

See Also

DatabaseManager, install

Source code in src/kaptive/db/manager.py
@classmethod
def known(cls) -> list[str]:
    r"""Return a list of keywords for all currently known, officially supported databases.

    These databases can be installed directly by providing their keyword to
    [`install`][kaptive.db.manager.DatabaseManager.install].

    Returns:
        list[str]: A list of known database keywords (e.g., `['kpsc_k', 'kpsc_o', 'kosc_k', ...]`).

    See Also:
        [`DatabaseManager`][kaptive.db.manager.DatabaseManager],
        [`install`][kaptive.db.manager.DatabaseManager.install]
    """
    return list(cls._KNOWN.keys())

load classmethod

load(kwd: str) -> Database

Load a locally installed, compiled database using its keyword.

Reads and unpickles the serialized .pkl database file from the local cache directory.

Parameters:

  • kwd

    (str) –

    The keyword identifier of the database to load (e.g., 'kpsc_k').

Returns:

Raises:

  • DatabaseError –

    If the specified database is not installed locally.

See Also

DatabaseManager, Database, DatabaseError

Source code in src/kaptive/db/manager.py
@classmethod
def load(cls, kwd: str) -> Database:
    r"""Load a locally installed, compiled database using its keyword.

    Reads and unpickles the serialized `.pkl` database file from the local cache directory.

    Args:
        kwd (str): The keyword identifier of the database to load (e.g., `'kpsc_k'`).

    Returns:
        Database: The deserialized [`Database`][kaptive.db.core.Database] instance.

    Raises:
        DatabaseError: If the specified database is not installed locally.

    See Also:
        [`DatabaseManager`][kaptive.db.manager.DatabaseManager],
        [`Database`][kaptive.db.core.Database],
        [`DatabaseError`][kaptive.db.models.DatabaseError]
    """
    return pickle.loads(cls._get_existing_db_path(kwd).read_bytes())

reset classmethod

reset() -> None

Remove all installed databases by deleting their compiled files from the local directory.

This clears the user's ~/.kaptive cache directory of any .pkl database files and .json metadata sidecar files, effectively uninstalling all downloaded and compiled databases.

Returns:

  • None –

    None

See Also

DatabaseManager, uninstall

Source code in src/kaptive/db/manager.py
@classmethod
def reset(cls) -> None:
    r"""Remove all installed databases by deleting their compiled files from the local directory.

    This clears the user's `~/.kaptive` cache directory of any `.pkl` database files and `.json` metadata
    sidecar files, effectively uninstalling all downloaded and compiled databases.

    Returns:
        None

    See Also:
        [`DatabaseManager`][kaptive.db.manager.DatabaseManager],
        [`uninstall`][kaptive.db.manager.DatabaseManager.uninstall]
    """
    if cls._DB_DIR.exists():
        for file_path in cls._DB_DIR.glob("*.pkl"):
            file_path.unlink()
        for file_path in cls._DB_DIR.glob("*.json"):
            file_path.unlink()

save classmethod

save(db: Database) -> int

Serialize and save a compiled Database object and its metadata to local storage.

Saves the database as a .pkl file named {keyword}.pkl in the local cache directory (_DB_DIR). Also writes a companion {keyword}.json file containing the serialized metadata for fast version checking.

Parameters:

Returns:

  • int ( int ) –

    The total number of bytes written to the .pkl database file.

See Also

DatabaseManager, Database, DatabaseMetadata

Source code in src/kaptive/db/manager.py
@classmethod
def save(cls, db: Database) -> int:
    r"""Serialize and save a compiled Database object and its metadata to local storage.

    Saves the database as a `.pkl` file named `{keyword}.pkl` in the local cache directory (`_DB_DIR`).
    Also writes a companion `{keyword}.json` file containing the serialized metadata for fast version checking.

    Args:
        db (Database): The compiled [`Database`][kaptive.db.core.Database] object to save.

    Returns:
        int: The total number of bytes written to the `.pkl` database file.

    See Also:
        [`DatabaseManager`][kaptive.db.manager.DatabaseManager],
        [`Database`][kaptive.db.core.Database],
        [`DatabaseMetadata`][kaptive.db.models.DatabaseMetadata]
    """
    db_path = cls._get_db_path(db.metadata.keyword)
    db_path.with_suffix(".json").write_text(json.dumps(asdict(db.metadata)))
    return db_path.write_bytes(pickle.dumps(db, protocol=pickle.HIGHEST_PROTOCOL))

uninstall classmethod

uninstall(kwd: str) -> None

Uninstall a specific database by removing its compiled local .pkl and .json files.

Parameters:

  • kwd

    (str) –

    The keyword of the database to uninstall (e.g., 'kpsc_k').

Returns:

  • None –

    None

Raises:

  • DatabaseError –

    If the specified database is not currently installed locally.

See Also

DatabaseManager, DatabaseError

Source code in src/kaptive/db/manager.py
@classmethod
def uninstall(cls, kwd: str) -> None:
    r"""Uninstall a specific database by removing its compiled local `.pkl` and `.json` files.

    Args:
        kwd (str): The keyword of the database to uninstall (e.g., `'kpsc_k'`).

    Returns:
        None

    Raises:
        DatabaseError: If the specified database is not currently installed locally.

    See Also:
        [`DatabaseManager`][kaptive.db.manager.DatabaseManager],
        [`DatabaseError`][kaptive.db.models.DatabaseError]
    """
    db_path = cls._get_existing_db_path(kwd)
    db_path.unlink()
    if db_path.with_suffix(".json").exists():
        db_path.with_suffix(".json").unlink()

update classmethod

update(kwd: str | list[str] = 'all') -> Generator[Database, None, None]

Update installed databases by checking against their remote GitHub repositories.

Extracts local metadata to determine the source repository and version, then checks the remote GitHub repository for a newer version. If a newer version is available, the source files (.gbk and .toml) are fetched, compiled into a new Database object, and saved to disk. When updating multiple databases or "all", remote fetches are executed concurrently using a thread pool executor.

Parameters:

  • kwd

    (str | list[str], default: 'all' ) –

    The keyword(s) of the database to update (e.g., 'kpsc_k', ['kpsc_k', 'ab_k'], or 'all'). Defaults to "all", which updates all currently installed databases.

Yields:

  • Database ( Database ) –

    The newly compiled Database object for each database that required an update. Databases that are already up-to-date yield nothing.

Raises:

  • DatabaseError –

    If a requested database is not installed locally, or if network/parsing failures occur during update.

See Also

installed, add, DatabaseManager, Database, DatabaseMetadata, DatabaseError

Source code in src/kaptive/db/manager.py
@classmethod
def update(cls, kwd: str | list[str] = "all") -> Generator[Database, None, None]:
    r"""Update installed databases by checking against their remote GitHub repositories.

    Extracts local metadata to determine the source repository and version, then checks the remote GitHub
    repository for a newer version. If a newer version is available, the source files (`.gbk` and `.toml`)
    are fetched, compiled into a new [`Database`][kaptive.db.core.Database] object, and saved to disk. When
    updating multiple databases or `"all"`, remote fetches are executed concurrently using a thread pool executor.

    Args:
        kwd (str | list[str]): The keyword(s) of the database to update (e.g., `'kpsc_k'`,
            `['kpsc_k', 'ab_k']`, or `'all'`). Defaults to `"all"`, which updates all currently installed databases.

    Yields:
        Database: The newly compiled [`Database`][kaptive.db.core.Database] object for each database that
            required an update. Databases that are already up-to-date yield nothing.

    Raises:
        DatabaseError: If a requested database is not installed locally, or if network/parsing failures occur
            during update.

    See Also:
        [`installed`][kaptive.db.manager.DatabaseManager.installed],
        [`add`][kaptive.db.manager.DatabaseManager.add],
        [`DatabaseManager`][kaptive.db.manager.DatabaseManager],
        [`Database`][kaptive.db.core.Database],
        [`DatabaseMetadata`][kaptive.db.models.DatabaseMetadata],
        [`DatabaseError`][kaptive.db.models.DatabaseError]
    """
    if kwd == "all":
        kwd = cls.installed()
        if not kwd:
            return

    if isinstance(kwd, list):

        def _fetch_update_one(k: str):
            db_path = cls._get_existing_db_path(k)
            json_path = db_path.with_suffix(".json")
            if json_path.is_file():
                meta = DatabaseMetadata.from_dict(json.loads(json_path.read_text()))
            else:
                meta = pickle.loads(db_path.read_bytes()).metadata
            db_name = Path(meta.genbank).with_suffix("").name
            return cls._fetch_files(meta.owner, meta.repo, db_name, branch=meta.branch, local_meta=meta)

        with concurrent.futures.ThreadPoolExecutor() as executor:
            fetched_list = list(executor.map(_fetch_update_one, kwd))

        for fetched in fetched_list:
            if fetched is not None:
                yield cls._compile_and_save(*fetched)
    else:
        db_path = cls._get_existing_db_path(kwd)
        json_path = db_path.with_suffix(".json")
        if json_path.is_file():
            meta = DatabaseMetadata.from_dict(json.loads(json_path.read_text()))
        else:
            meta = pickle.loads(db_path.read_bytes()).metadata
        db_name = Path(meta.genbank).with_suffix("").name
        if (res := cls.add(meta.owner, meta.repo, db_name, branch=meta.branch, local_meta=meta)) is not None:
            yield res