LCOV - code coverage report
Current view: top level - src/pairinteraction/database - database.py (source / functions) Hit Total Coverage
Test: coverage.info Lines: 35 42 83.3 %
Date: 2026-09-10 17:43:59 Functions: 7 9 77.8 %

          Line data    Source code
       1             : # SPDX-FileCopyrightText: 2024 PairInteraction Developers
       2             : # SPDX-License-Identifier: LGPL-3.0-or-later
       3           1 : from __future__ import annotations
       4             : 
       5           1 : import logging
       6           1 : from typing import TYPE_CHECKING, ClassVar
       7             : 
       8           1 : from pairinteraction import _backend
       9           1 : from pairinteraction.custom_logging import _flush_pending_logs
      10             : 
      11             : if TYPE_CHECKING:
      12             :     import os
      13             :     from pathlib import Path
      14             : 
      15             : 
      16           1 : logger = logging.getLogger(__name__)
      17             : 
      18             : 
      19           1 : class Database:
      20             :     """Class for handling the databases for the PairInteraction package.
      21             : 
      22             :     The Databases are used to store the atomic states, their energies, and their matrix elements to other states.
      23             :     The databases are stored in the user's cache directory by default, but can be stored in a different directory.
      24             :     When running PairInteraction for the first time, the databases have to be downloaded from the internet
      25             :     (e.g. by explicitly passing `download_missing=True` to the constructor).
      26             :     Once the databases are downloaded, the user usually does not have to interact with the Database class directly.
      27             : 
      28             :     """
      29             : 
      30           1 :     _global_database: ClassVar[Database | None] = None
      31             : 
      32           1 :     def __init__(
      33             :         self,
      34             :         download_missing: bool = False,
      35             :         use_cache: bool = True,
      36             :         database_dir: str | os.PathLike[str] = "",
      37             :     ) -> None:
      38             :         """Create a new database instance with the given parameters.
      39             : 
      40             :         Args:
      41             :             download_missing: Whether to download missing databases if needed. Default False.
      42             :             use_cache: Whether to load the Wigner 3j symbols table into memory. Default True.
      43             :             database_dir: The directory where the databases are stored.
      44             :                 Default "", i.e. use the default directory (the user's cache directory).
      45             : 
      46             :         """
      47           1 :         self._cpp = _backend.Database(download_missing, use_cache, database_dir)
      48           1 :         _flush_pending_logs()  # call it manually because constructors of classes from nanobind cannot be decorated
      49             : 
      50           1 :     @classmethod
      51           1 :     def _from_cpp_object(cls, cpp_obj: _backend.Database) -> Database:
      52             :         """Create a Database instance from a C++ Database object.
      53             : 
      54             :         This is used internally to convert C++ objects returned by the C++ API to Python objects.
      55             :         """
      56           1 :         obj = cls.__new__(cls)
      57           1 :         obj._cpp = cpp_obj
      58           1 :         return obj
      59             : 
      60           1 :     @classmethod
      61           1 :     def get_global_database(cls) -> Database:
      62             :         """Return the global database instance if it was initialized, otherwise None."""
      63           1 :         return cls._global_database  # type: ignore [return-value]
      64             : 
      65           1 :     @classmethod
      66           1 :     def initialize_global_database(
      67             :         cls,
      68             :         download_missing: bool = False,
      69             :         use_cache: bool = True,
      70             :         database_dir: str | os.PathLike[str] = "",
      71             :     ) -> None:
      72             :         """Initialize the global database with the given parameters.
      73             : 
      74             :         The arguments are the same as for the constructor of this class.
      75             :         """
      76           1 :         db = cls(download_missing, use_cache, database_dir)
      77           1 :         if cls._global_database is None:
      78           1 :             cls._global_database = db
      79           0 :         elif (
      80             :             cls._global_database.download_missing == db.download_missing
      81             :             and cls._global_database.use_cache == db.use_cache
      82             :             and cls._global_database.database_dir == db.database_dir
      83             :         ):
      84           0 :             pass  # already initialized with the same parameters
      85             :         else:
      86           0 :             raise ValueError(
      87             :                 "Global database was already initialized with different parameters. "
      88             :                 "The global database is automatically initialized when needed. "
      89             :                 "If you explicitly want to initialize the global database, do this at the beginning of your script."
      90             :             )
      91             : 
      92           1 :     @property
      93           1 :     def download_missing(self) -> bool:
      94             :         """Whether to download missing databases if needed."""
      95           1 :         return self._cpp.get_download_missing()
      96             : 
      97           1 :     @property
      98           1 :     def use_cache(self) -> bool:
      99             :         """Whether to load the Wigner 3j symbols table into memory."""
     100           1 :         return self._cpp.get_use_cache()
     101             : 
     102           1 :     @property
     103           1 :     def database_dir(self) -> Path:
     104             :         """The directory where the databases are stored."""
     105           1 :         return self._cpp.get_database_dir()
     106             : 
     107           1 :     def get_versions_info(self) -> str:
     108             :         """Return a formatted table of local and remote database versions."""
     109           0 :         return self._cpp.get_versions_info()
     110             : 
     111             : 
     112           1 : def print_database_info(
     113             :     download_missing: bool = True,
     114             :     use_cache: bool = True,
     115             :     database_dir: str | os.PathLike[str] = "",
     116             : ) -> None:
     117             :     """Print an overview of local and remote database tables."""
     118           0 :     db = Database(download_missing, use_cache, database_dir)
     119           0 :     print(f"Database directory: {db.database_dir}")
     120           0 :     print(db.get_versions_info())

Generated by: LCOV version 1.16