-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into fix_247_remove_commented_gha_job
- Loading branch information
Showing
36 changed files
with
5,847 additions
and
30 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 |
---|---|---|
@@ -0,0 +1,14 @@ | ||
--- | ||
profile: PLACEHOLDER_PROFILE | ||
email: aiida@localhost | ||
first_name: AiiDA | ||
last_name: OPTIMADE | ||
institution: Materials-Consortia | ||
db_backend: PLACEHOLDER_BACKEND | ||
db_engine: postgresql_psycopg2 | ||
db_host: localhost | ||
db_port: 5432 | ||
db_name: PLACEHOLDER_DATABASE_NAME | ||
db_username: postgres | ||
db_password: test | ||
repository: PLACEHOLDER_REPOSITORY |
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,13 @@ | ||
#!/usr/bin/env bash | ||
set -ev | ||
|
||
# Replace the placeholders in configuration files with actual values | ||
CONFIG="${GITHUB_WORKSPACE}/.github/aiida" | ||
sed -i "s|PLACEHOLDER_BACKEND|${AIIDA_TEST_BACKEND}|" "${CONFIG}/profile.yaml" | ||
sed -i "s|PLACEHOLDER_PROFILE|test_${AIIDA_TEST_BACKEND}|" "${CONFIG}/profile.yaml" | ||
sed -i "s|PLACEHOLDER_DATABASE_NAME|test_${AIIDA_TEST_BACKEND}|" "${CONFIG}/profile.yaml" | ||
sed -i "s|PLACEHOLDER_REPOSITORY|/tmp/test_repository_test_${AIIDA_TEST_BACKEND}/|" "${CONFIG}/profile.yaml" | ||
|
||
verdi setup --config "${CONFIG}/profile.yaml" | ||
|
||
verdi profile setdefault test_${AIIDA_TEST_BACKEND} |
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
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,7 @@ | ||
# pylint: disable=undefined-variable | ||
from .exceptions import * | ||
from .references import * | ||
from .structures import * | ||
|
||
|
||
__all__ = exceptions.__all__ + references.__all__ + structures.__all__ |
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,120 @@ | ||
import re | ||
from typing import Union, Dict, Callable, Any, Tuple, List | ||
|
||
from pydantic import BaseModel # pylint: disable=no-name-in-module | ||
|
||
from optimade.models import EntryResource | ||
|
||
|
||
class EntryAdapter: | ||
"""Base class for lazy resource entry adapters | ||
:param entry: JSON OPTIMADE single resource entry. | ||
""" | ||
|
||
ENTRY_RESOURCE: EntryResource = EntryResource | ||
_type_converters: Dict[str, Callable] = {} | ||
|
||
def __init__(self, entry: dict): | ||
self._entry = None | ||
self._converted = {} | ||
|
||
self.entry = entry | ||
|
||
# Note that these return also the default values for otherwise non-provided properties. | ||
self._common_converters = { | ||
"json": self.entry.json, # Return JSON serialized string, see https://pydantic-docs.helpmanual.io/usage/exporting_models/#modeljson | ||
"dict": self.entry.dict, # Return Python dict, see https://pydantic-docs.helpmanual.io/usage/exporting_models/#modeldict | ||
} | ||
|
||
@property | ||
def entry(self): | ||
"""Get OPTIMADE entry""" | ||
return self._entry | ||
|
||
@entry.setter | ||
def entry(self, value: dict): | ||
"""Set OPTIMADE entry | ||
If already set, print that this can _only_ be set once. | ||
""" | ||
if self._entry is None: | ||
self._entry = self.ENTRY_RESOURCE(**value) | ||
else: | ||
print("entry can only be set once and is already set.") | ||
|
||
def convert(self, format: str) -> Any: | ||
"""Convert OPTIMADE entry to desired format""" | ||
if ( | ||
format not in self._type_converters | ||
and format not in self._common_converters | ||
): | ||
raise AttributeError( | ||
f"Non-valid entry type to convert to: {format}\n" | ||
f"Valid entry types: {tuple(self._type_converters.keys()) + tuple(self._common_converters.keys())}" | ||
) | ||
|
||
if self._converted.get(format, None) is None: | ||
if format in self._type_converters: | ||
self._converted[format] = self._type_converters[format](self.entry) | ||
else: | ||
self._converted[format] = self._common_converters[format]() | ||
|
||
return self._converted[format] | ||
|
||
@staticmethod | ||
def _get_model_attributes( | ||
starting_instances: Union[Tuple[BaseModel], List[BaseModel]], name: str | ||
) -> Any: | ||
"""Helper method for retrieving the OPTIMADE model's attribute, supporting "."-nested attributes""" | ||
for res in starting_instances: | ||
nested_attributes = name.split(".") | ||
for nested_attribute in nested_attributes: | ||
if nested_attribute in getattr(res, "__fields__", {}): | ||
res = getattr(res, nested_attribute) | ||
else: | ||
res = None | ||
break | ||
if res is not None: | ||
return res | ||
raise AttributeError | ||
|
||
def __getattr__(self, name: str) -> Any: | ||
"""Get converted entry or attribute from OPTIMADE entry | ||
Support any level of "."-nested OPTIMADE ENTRY_RESOURCE attributes, e.g., `attributes.species` for StuctureResource. | ||
NOTE: All nested attributes must individually be subclasses of `pydantic.BaseModel`, | ||
i.e., one can not access nested attributes in lists by passing a "."-nested `name` to this method, | ||
e.g., `attributes.species.name` or `attributes.species[0].name` will not work for variable `name`. | ||
Order: | ||
- Try to return converted entry if using `as_<_type_converters key>`. | ||
- Try to return OPTIMADE ENTRY_RESOURCE (nested) attribute. | ||
- Try to return OPTIMADE ENTRY_RESOURCE.attributes (nested) attribute. | ||
- Raise AttributeError | ||
""" | ||
# as_<entry_type> | ||
if name.startswith("as_"): | ||
entry_type = "_".join(name.split("_")[1:]) | ||
return self.convert(entry_type) | ||
|
||
# Try returning ENTRY_RESOURCE attribute | ||
try: | ||
res = self._get_model_attributes((self.entry, self.entry.attributes), name) | ||
except AttributeError: | ||
pass | ||
else: | ||
return res | ||
|
||
# Non-valid attribute | ||
entry_resource_name = re.match( | ||
r"(<class ')([a-zA-Z_]+\.)*([a-zA-Z_]+)('>)", str(self.ENTRY_RESOURCE) | ||
) | ||
entry_resource_name = ( | ||
entry_resource_name.group(3) | ||
if entry_resource_name is not None | ||
else "UNKNOWN RESOURCE" | ||
) | ||
raise AttributeError( | ||
f"Unknown attribute: {name}\n" | ||
"If you want to get a converted entry as <entry_type> use `as_<entry_type>`, " | ||
f"where `<entry_type>` is one of {tuple(self._type_converters.keys()) + tuple(self._common_converters.keys())}\n" | ||
f"Otherwise, you can try to retrieve an OPTIMADE {entry_resource_name} attribute or property." | ||
) |
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,5 @@ | ||
__all__ = ("ConversionError",) | ||
|
||
|
||
class ConversionError(Exception): | ||
"""Could not convert entry to format""" |
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,16 @@ | ||
from typing import Union | ||
|
||
from optimade.models import ReferenceResource | ||
|
||
from optimade.adapters.base import EntryAdapter | ||
|
||
|
||
__all__ = ("Reference",) | ||
|
||
|
||
class Reference(EntryAdapter): | ||
"""Lazy reference resource converter | ||
:param reference: a single JSON OPTIMADE reference resource entry. | ||
""" | ||
|
||
ENTRY_RESOURCE = ReferenceResource |
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,30 @@ | ||
from typing import Union | ||
|
||
from optimade.models import StructureResource | ||
|
||
from optimade.adapters.base import EntryAdapter | ||
|
||
from .aiida import get_aiida_structure_data | ||
from .ase import get_ase_atoms | ||
from .cif import get_cif | ||
from .proteindatabank import get_pdb, get_pdbx_mmcif | ||
from .pymatgen import get_pymatgen | ||
|
||
|
||
__all__ = ("Structure",) | ||
|
||
|
||
class Structure(EntryAdapter): | ||
"""Lazy structure resource converter | ||
:param structure: a single JSON OPTIMADE structure resource entry. | ||
""" | ||
|
||
ENTRY_RESOURCE = StructureResource | ||
_type_converters = { | ||
"aiida_structuredata": get_aiida_structure_data, | ||
"ase": get_ase_atoms, | ||
"cif": get_cif, | ||
"pdb": get_pdb, | ||
"pdbx_mmcif": get_pdbx_mmcif, | ||
"pymatgen": get_pymatgen, | ||
} |
Oops, something went wrong.