-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use custom
WorkflowFactory
to provide plugin install instructions
The `WorkflowFactory` from `aiida-core` is replaced with a custom version in the `aiida_common_workflows.plugins.factories` module. This function will call the factory from `aiida-core` but catch the `MissingEntryPointError` exception. In this case, if the entry point corresponds to a plugin implementation of one of the common workflows the exception is reraised but with a useful message that provides the user with the install command to install the necessary plugin package. While this should catch all cases of users trying to load a workflow for a plugin that is not installed through its entry point, it won't catch import errors that are raised when a module is imported directly from that plugin package. Therefore, these imports should not be placed at the top of modules, but placed inside functions/methods of the implementation as much as possible.
- Loading branch information
Showing
7 changed files
with
98 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,10 @@ | ||
"""Module with utilities for working with the plugins provided by this plugin package.""" | ||
from .entry_point import get_entry_point_name_from_class, get_workflow_entry_point_names, load_workflow_entry_point | ||
from .factories import WorkflowFactory | ||
|
||
__all__ = ('get_workflow_entry_point_names', 'get_entry_point_name_from_class', 'load_workflow_entry_point') | ||
__all__ = ( | ||
'WorkflowFactory', | ||
'get_workflow_entry_point_names', | ||
'get_entry_point_name_from_class', | ||
'load_workflow_entry_point', | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
"""Factories to load entry points.""" | ||
import typing as t | ||
|
||
from aiida import plugins | ||
from aiida.common import exceptions | ||
|
||
if t.TYPE_CHECKING: | ||
from aiida.engine import WorkChain | ||
from importlib_metadata import EntryPoint | ||
|
||
__all__ = ('WorkflowFactory',) | ||
|
||
|
||
@t.overload | ||
def WorkflowFactory(entry_point_name: str, load: t.Literal[True] = True) -> t.Union[t.Type['WorkChain'], t.Callable]: | ||
... | ||
|
||
|
||
@t.overload | ||
def WorkflowFactory(entry_point_name: str, load: t.Literal[False]) -> 'EntryPoint': | ||
... | ||
|
||
|
||
def WorkflowFactory(entry_point_name: str, load: bool = True) -> t.Union['EntryPoint', t.Type['WorkChain'], t.Callable]: # noqa: N802 | ||
"""Return the `WorkChain` sub class registered under the given entry point. | ||
:param entry_point_name: the entry point name. | ||
:param load: if True, load the matched entry point and return the loaded resource instead of the entry point itself. | ||
:return: sub class of :py:class:`~aiida.engine.processes.workchains.workchain.WorkChain` or a `workfunction` | ||
:raises aiida.common.MissingEntryPointError: entry point was not registered | ||
:raises aiida.common.MultipleEntryPointError: entry point could not be uniquely resolved | ||
:raises aiida.common.LoadingEntryPointError: entry point could not be loaded | ||
:raises aiida.common.InvalidEntryPointTypeError: if the type of the loaded entry point is invalid. | ||
""" | ||
common_workflow_prefixes = ('common_workflows.relax.', 'common_workflows.bands.') | ||
try: | ||
return plugins.WorkflowFactory(entry_point_name, load) | ||
except exceptions.MissingEntryPointError as exception: | ||
for prefix in common_workflow_prefixes: | ||
if entry_point_name.startswith(prefix): | ||
plugin_name = entry_point_name.removeprefix(prefix) | ||
raise exceptions.MissingEntryPointError( | ||
f'Could not load the entry point `{entry_point_name}`, probably because the plugin package is not ' | ||
f'installed. Please install it with `pip install aiida-common-workflows[{plugin_name}]`.' | ||
) from exception | ||
else: # noqa: PLW0120 | ||
raise |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters