diff --git a/src/aiida/cmdline/commands/cmd_presto.py b/src/aiida/cmdline/commands/cmd_presto.py index 7f455e5c74..c7ca64ab5a 100644 --- a/src/aiida/cmdline/commands/cmd_presto.py +++ b/src/aiida/cmdline/commands/cmd_presto.py @@ -67,7 +67,7 @@ def detect_postgres_config( """ import secrets - from aiida.manage.configuration.settings import glb_aiida_config_folder + from aiida.manage.configuration.settings import get_configuration_directory from aiida.manage.external.postgres import Postgres dbinfo = { @@ -92,13 +92,15 @@ def detect_postgres_config( except Exception as exception: raise ConnectionError(f'Unable to automatically create the PostgreSQL user and database: {exception}') + aiida_config_folder = get_configuration_directory() + return { 'database_hostname': postgres_hostname, 'database_port': postgres_port, 'database_name': database_name, 'database_username': database_username, 'database_password': database_password, - 'repository_uri': f'file://{glb_aiida_config_folder / "repository" / profile_name}', + 'repository_uri': f'file://{aiida_config_folder / "repository" / profile_name}', } diff --git a/src/aiida/cmdline/commands/cmd_profile.py b/src/aiida/cmdline/commands/cmd_profile.py index 78537842a2..5fdd2f9944 100644 --- a/src/aiida/cmdline/commands/cmd_profile.py +++ b/src/aiida/cmdline/commands/cmd_profile.py @@ -169,9 +169,9 @@ def profile_list(): # This can happen for a fresh install and the `verdi setup` has not yet been run. In this case it is still nice # to be able to see the configuration directory, for instance for those who have set `AIIDA_PATH`. This way # they can at least verify that it is correctly set. - from aiida.manage.configuration.settings import glb_aiida_config_folder + from aiida.manage.configuration.settings import get_configuration_directory - echo.echo_report(f'configuration folder: {glb_aiida_config_folder}') + echo.echo_report(f'configuration folder: {get_configuration_directory()}') echo.echo_critical(str(exception)) else: echo.echo_report(f'configuration folder: {config.dirpath}') diff --git a/src/aiida/cmdline/commands/cmd_status.py b/src/aiida/cmdline/commands/cmd_status.py index af1249fa32..0186f473f9 100644 --- a/src/aiida/cmdline/commands/cmd_status.py +++ b/src/aiida/cmdline/commands/cmd_status.py @@ -61,13 +61,14 @@ def verdi_status(print_traceback, no_rmq): from aiida.common.docs import URL_NO_BROKER from aiida.common.exceptions import ConfigurationError from aiida.engine.daemon.client import DaemonException, DaemonNotRunningException - from aiida.manage.configuration.settings import glb_aiida_config_folder + from aiida.manage.configuration.settings import get_configuration_directory from aiida.manage.manager import get_manager exit_code = ExitCode.SUCCESS + configure_directory = get_configuration_directory() print_status(ServiceStatus.UP, 'version', f'AiiDA v{__version__}') - print_status(ServiceStatus.UP, 'config', glb_aiida_config_folder) + print_status(ServiceStatus.UP, 'config', str(configure_directory)) manager = get_manager() diff --git a/src/aiida/cmdline/params/options/commands/setup.py b/src/aiida/cmdline/params/options/commands/setup.py index 10ff2412a6..fc4f031aa3 100644 --- a/src/aiida/cmdline/params/options/commands/setup.py +++ b/src/aiida/cmdline/params/options/commands/setup.py @@ -66,11 +66,11 @@ def get_repository_uri_default(ctx): """ import os - from aiida.manage.configuration.settings import glb_aiida_config_folder + from aiida.manage.configuration.settings import get_configuration_directory validate_profile_parameter(ctx) - return os.path.join(glb_aiida_config_folder, 'repository', ctx.params['profile'].name) + return os.path.join(get_configuration_directory(), 'repository', ctx.params['profile'].name) def get_quicksetup_repository_uri(ctx, param, value): diff --git a/src/aiida/manage/configuration/__init__.py b/src/aiida/manage/configuration/__init__.py index f9151d30ff..d1f3b07de5 100644 --- a/src/aiida/manage/configuration/__init__.py +++ b/src/aiida/manage/configuration/__init__.py @@ -66,9 +66,9 @@ def get_config_path(): """Returns path to .aiida configuration directory.""" - from .settings import DEFAULT_CONFIG_FILE_NAME, glb_aiida_config_folder + from .settings import DEFAULT_CONFIG_FILE_NAME, get_configuration_directory - return os.path.join(glb_aiida_config_folder, DEFAULT_CONFIG_FILE_NAME) + return os.path.join(str(get_configuration_directory()), DEFAULT_CONFIG_FILE_NAME) def load_config(create=False) -> 'Config': diff --git a/src/aiida/manage/configuration/profile.py b/src/aiida/manage/configuration/profile.py index d1d586f8b3..bd917f3130 100644 --- a/src/aiida/manage/configuration/profile.py +++ b/src/aiida/manage/configuration/profile.py @@ -18,7 +18,7 @@ from aiida.common import exceptions from aiida.common.lang import type_check -from aiida.manage.configuration.settings import AiiDAConfigPathResolver +from aiida.manage.configuration.settings import AiiDAConfigPathResolver, get_configuration_directory from .options import parse_option @@ -67,7 +67,9 @@ def __init__( self._attributes[self.KEY_UUID] = uuid4().hex - self._config_path_resolver: AiiDAConfigPathResolver = AiiDAConfigPathResolver(config_folder) + self._config_path_resolver: AiiDAConfigPathResolver = AiiDAConfigPathResolver( + config_folder or get_configuration_directory() + ) def __repr__(self) -> str: return f'Profile' diff --git a/src/aiida/manage/configuration/settings.py b/src/aiida/manage/configuration/settings.py index 892d98f9ba..6b844b4b04 100644 --- a/src/aiida/manage/configuration/settings.py +++ b/src/aiida/manage/configuration/settings.py @@ -27,21 +27,15 @@ DEFAULT_ACCESS_CONTROL_DIR_NAME = 'access' # Assign defaults which may be overriden in set_configuration_directory() below -glb_aiida_config_folder: pathlib.Path = pathlib.Path(DEFAULT_AIIDA_PATH).expanduser() / DEFAULT_CONFIG_DIR_NAME +_glb_aiida_config_folder: pathlib.Path = pathlib.Path(DEFAULT_AIIDA_PATH).expanduser() / DEFAULT_CONFIG_DIR_NAME @final class AiiDAConfigPathResolver: - """Path resolver for getting daemon dir, daemon log dir and access control dir location. + """Path resolver for getting daemon dir, daemon log dir and access control dir location.""" - If ``config_folder`` is ``None``, ``~/.aiida`` will be the default root config folder. - """ - - def __init__(self, config_folder: pathlib.Path | None = None) -> None: - if config_folder is None: - self._aiida_path = glb_aiida_config_folder - else: - self._aiida_path = config_folder + def __init__(self, config_folder: pathlib.Path) -> None: + self._aiida_path = config_folder @property def aiida_path(self) -> pathlib.Path: @@ -63,12 +57,13 @@ def access_control_dir(self) -> pathlib.Path: def create_instance_directories(aiida_config_folder: pathlib.Path | None) -> None: """Create the base directories required for a new AiiDA instance. - This will create the base AiiDA directory defined by the glb_aiida_config_folder variable, unless it already exists. + This will create the base AiiDA directory defined by the _glb_aiida_config_folder variable, + unless it already exists. Subsequently, it will create the daemon directory within it and the daemon log directory. """ from aiida.common import ConfigurationError - path_resolver = AiiDAConfigPathResolver(aiida_config_folder) + path_resolver = AiiDAConfigPathResolver(aiida_config_folder or _glb_aiida_config_folder) list_of_paths = [ path_resolver.aiida_path, @@ -98,22 +93,16 @@ def get_configuration_directory(): The location of the configuration directory is defined following these heuristics in order: * If the ``AIIDA_PATH`` variable is set, all the paths will be checked to see if they contain a - configuration folder. The first one to be encountered will be set as ``glb_aiida_config_folder``. + configuration folder. The first one to be encountered will be set as ``_glb_aiida_config_folder``. If none of them contain one, the last path defined in the environment variable considered is used. * If an existing directory is still not found, the ``DEFAULT_AIIDA_PATH`` is used. :returns: The path of the configuration directory. """ - dirpath_config = get_configuration_directory_from_envvar() - - # If no existing configuration directory is found, fall back to the default - if dirpath_config is None: - dirpath_config = pathlib.Path(DEFAULT_AIIDA_PATH).expanduser() / DEFAULT_CONFIG_DIR_NAME - - return dirpath_config + return _glb_aiida_config_folder -def get_configuration_directory_from_envvar() -> pathlib.Path | None: +def get_configuration_directory_from_envvar() -> pathlib.Path: """Return the path of a config directory from the ``AIIDA_PATH`` environment variable. The environment variable should be a colon separated string of filepaths that either point directly to a config @@ -124,12 +113,13 @@ def get_configuration_directory_from_envvar() -> pathlib.Path | None: """ environment_variable = os.environ.get(DEFAULT_AIIDA_PATH_VARIABLE) - if environment_variable is None: - return None + default_dirpath_config = pathlib.Path(DEFAULT_AIIDA_PATH).expanduser() / DEFAULT_CONFIG_DIR_NAME - dirpath_config = None + if environment_variable is None: + return default_dirpath_config # Loop over all the paths in the ``AIIDA_PATH`` variable to see if any of them contain a configuration folder + dirpath_config = None for base_dir_path in [path for path in environment_variable.split(':') if path]: dirpath_config = pathlib.Path(base_dir_path).expanduser() @@ -142,7 +132,7 @@ def get_configuration_directory_from_envvar() -> pathlib.Path | None: if dirpath_config.is_dir(): break - return dirpath_config + return dirpath_config or default_dirpath_config def set_configuration_directory(aiida_config_folder: pathlib.Path | None = None) -> None: @@ -152,10 +142,10 @@ def set_configuration_directory(aiida_config_folder: pathlib.Path | None = None) is returned by ``get_configuration_directory``. If the directory does not exist yet, it is created, together with all its subdirectories. """ - global glb_aiida_config_folder # noqa: PLW0603 - glb_aiida_config_folder = aiida_config_folder or get_configuration_directory() + global _glb_aiida_config_folder # noqa: PLW0603 + _glb_aiida_config_folder = aiida_config_folder or get_configuration_directory_from_envvar() - create_instance_directories(glb_aiida_config_folder) + create_instance_directories(_glb_aiida_config_folder) # Initialize the configuration directory settings diff --git a/src/aiida/manage/tests/pytest_fixtures.py b/src/aiida/manage/tests/pytest_fixtures.py index ddd9ef0d42..09818429cd 100644 --- a/src/aiida/manage/tests/pytest_fixtures.py +++ b/src/aiida/manage/tests/pytest_fixtures.py @@ -178,8 +178,7 @@ def aiida_instance( dirpath_config = tmp_path_factory.mktemp('config') os.environ[settings.DEFAULT_AIIDA_PATH_VARIABLE] = str(dirpath_config) - settings.glb_aiida_config_folder = dirpath_config - settings.set_configuration_directory() + settings.set_configuration_directory(dirpath_config) configuration.CONFIG = configuration.load_config(create=True) try: @@ -191,7 +190,7 @@ def aiida_instance( else: os.environ[settings.DEFAULT_AIIDA_PATH_VARIABLE] = current_path_variable - settings.glb_aiida_config_folder = current_config_path + settings.set_configuration_directory(current_config_path) configuration.CONFIG = current_config if current_profile: aiida_manager.load_profile(current_profile.name, allow_switch=True) diff --git a/src/aiida/storage/sqlite_dos/backend.py b/src/aiida/storage/sqlite_dos/backend.py index 4b48daa530..d4ff722fd4 100644 --- a/src/aiida/storage/sqlite_dos/backend.py +++ b/src/aiida/storage/sqlite_dos/backend.py @@ -26,7 +26,7 @@ from aiida.common import exceptions from aiida.common.log import AIIDA_LOGGER from aiida.manage.configuration.profile import Profile -from aiida.manage.configuration.settings import glb_aiida_config_folder +from aiida.manage.configuration.settings import get_configuration_directory from aiida.orm.implementation import BackendEntity from aiida.storage.log import MIGRATE_LOGGER from aiida.storage.psql_dos.models.settings import DbSetting @@ -203,7 +203,7 @@ class Model(BaseModel, defer_build=True): filepath: str = Field( title='Directory of the backend', description='Filepath of the directory in which to store data for this backend.', - default_factory=lambda: str(glb_aiida_config_folder / 'repository' / f'sqlite_dos_{uuid4().hex}'), + default_factory=lambda: str(get_configuration_directory() / 'repository' / f'sqlite_dos_{uuid4().hex}'), ) @field_validator('filepath') diff --git a/tests/manage/configuration/test_config.py b/tests/manage/configuration/test_config.py index 02f7254de0..d682f78dbd 100644 --- a/tests/manage/configuration/test_config.py +++ b/tests/manage/configuration/test_config.py @@ -69,7 +69,7 @@ def test_environment_variable_not_set(chdir_tmp_path, monkeypatch): config_folder = chdir_tmp_path / settings.DEFAULT_CONFIG_DIR_NAME assert os.path.isdir(config_folder) - assert settings.glb_aiida_config_folder == pathlib.Path(config_folder) + assert settings.get_configuration_directory() == pathlib.Path(config_folder) @pytest.mark.filterwarnings('ignore:Creating AiiDA configuration folder') @@ -83,7 +83,7 @@ def test_environment_variable_set_single_path_without_config_folder(tmp_path): # This should have created the configuration directory in the path config_folder = tmp_path / settings.DEFAULT_CONFIG_DIR_NAME assert config_folder.is_dir() - assert settings.glb_aiida_config_folder == config_folder + assert settings.get_configuration_directory() == config_folder @pytest.mark.filterwarnings('ignore:Creating AiiDA configuration folder') @@ -99,7 +99,7 @@ def test_environment_variable_set_single_path_with_config_folder(tmp_path): # This should have created the configuration directory in the path config_folder = tmp_path / settings.DEFAULT_CONFIG_DIR_NAME assert config_folder.is_dir() - assert settings.glb_aiida_config_folder == config_folder + assert settings.get_configuration_directory() == config_folder @pytest.mark.filterwarnings('ignore:Creating AiiDA configuration folder') @@ -119,7 +119,7 @@ def test_environment_variable_path_including_config_folder(tmp_path): # This should have created the configuration directory in the pathpath config_folder = tmp_path / settings.DEFAULT_CONFIG_DIR_NAME assert config_folder.is_dir() - assert settings.glb_aiida_config_folder == config_folder + assert settings.get_configuration_directory() == config_folder @pytest.mark.filterwarnings('ignore:Creating AiiDA configuration folder') @@ -142,7 +142,7 @@ def test_environment_variable_set_multiple_path(tmp_path): # This should have created the configuration directory in the last path config_folder = directory_c / settings.DEFAULT_CONFIG_DIR_NAME assert os.path.isdir(config_folder) - assert settings.glb_aiida_config_folder == config_folder + assert settings.get_configuration_directory() == config_folder def compare_config_in_memory_and_on_disk(config, filepath): diff --git a/tests/manage/test_caching_config.py b/tests/manage/test_caching_config.py index 50f4f46038..5f3b5126eb 100644 --- a/tests/manage/test_caching_config.py +++ b/tests/manage/test_caching_config.py @@ -49,7 +49,7 @@ def test_merge_deprecated_yaml(tmp_path): # Store the current configuration instance and config directory path current_config = configuration.CONFIG - current_config_path = current_config.dirpath + current_config_path = pathlib.Path(current_config.dirpath) current_profile_name = configuration.get_profile().name try: @@ -57,7 +57,7 @@ def test_merge_deprecated_yaml(tmp_path): configuration.CONFIG = None # Create a temporary folder, set it as the current config directory path - settings.glb_aiida_config_folder = str(tmp_path) + settings.set_configuration_directory(pathlib.Path(tmp_path)) config_dictionary = json.loads( pathlib.Path(__file__) .parent.joinpath('configuration/migrations/test_samples/reference/6.json') @@ -86,7 +86,7 @@ def test_merge_deprecated_yaml(tmp_path): # Reset the config folder path and the config instance. Note this will always be executed after the yield no # matter what happened in the test that used this fixture. get_manager().unload_profile() - settings.glb_aiida_config_folder = current_config_path + settings.set_configuration_directory(current_config_path) configuration.CONFIG = current_config load_profile(current_profile_name)