Skip to content

Commit

Permalink
Fix aiida.cmdline.utils.decorators.load_backend_if_not_loaded (#4878)
Browse files Browse the repository at this point in the history
The function incorrectly used the `PROFILE` global variable to determine
whether the database backend environment had been loaded. This variable
is set as soon as a profile is loaded, however, this does not
automatically mean that the database environment is also loaded. These
two actions are separate on purpose such that a profile can be loaded
without having to load the backend, since that is an expensive operation
and is not always necessary.

This bug meant that sometimes the backend would actually not be loaded
even though the `with_dbenv` decorator was correctly used. This affects,
among other things, all CLI commands that rely on the backend being
loaded but having no code in its execution path that will automatically
load the backend, such as `verdi archive import`. Any commands that deal
with the ORM still work, since loading any ORM entity will automatically
load the backend of the current profile if not already done. Since the
import functionality circumvents the ORM, it didn't have this failsafe
operation.

Finally, the bug was not noticed by the unittests because they run in an
environment where the database backend is loaded anyway for the test
profile effectively hiding the bug of the `load_backend_if_not_loaded`
method.
  • Loading branch information
sphuber authored Apr 28, 2021
1 parent 16b326b commit e335e30
Showing 1 changed file with 14 additions and 7 deletions.
21 changes: 14 additions & 7 deletions aiida/cmdline/utils/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
code branch gets visited and possibly avoiding the overhead if not
"""

from contextlib import contextmanager

from click_spinner import spinner
Expand All @@ -33,18 +32,26 @@


def load_backend_if_not_loaded():
"""Load the current profile if necessary while running the spinner to show command hasn't crashed."""
from aiida.manage.configuration import load_profile, PROFILE
"""Load the database backend environment for the currently loaded profile.
If no profile has been loaded yet, the default profile will be loaded first. A spinner will be shown during both
actions to indicate that the function is working and has not crashed, since loading can take a second.
"""
from aiida.manage.configuration import get_profile, load_profile
from aiida.manage.manager import get_manager

if PROFILE is None:
manager = get_manager()

if get_profile() is None or not manager.backend_loaded:
with spinner():
load_profile()
get_manager().get_backend()
load_profile() # This will load the default profile if no profile has already been loaded
manager.get_backend() # This will load the backend of the loaded profile, if not already loaded


def with_dbenv():
"""Function decorator that will load the database environment only when the function is called.
"""Function decorator that will load the database environment for the currently loaded profile.
.. note:: if no profile has been loaded yet, the default profile will be loaded first.
Example::
Expand Down

0 comments on commit e335e30

Please sign in to comment.