Skip to content

Commit

Permalink
Dependencies: update requirement aiida-core~=2.0
Browse files Browse the repository at this point in the history
Adds compatibility with AiiDA v2.0. Notable changes:

* Entry points are now loaded through built-in modules instead of the
  custom `reentry`, so `reentry scan` no longer needs to be called.
* Tab-completion now ships with `click` itself, so `click_completion`
  and its manual activiation is removed.
* Update entry points from `aiida-core` by prefixing with `core.`

Also enable the `AIIDA_WARN_v3` environment variable in the `tests` job
of the CI workflow. This will print deprecation warnings from
`aiida-core`. These are also addressed in this commit:

* `Entity.objects` -> `Entity.collection`
* `Node.get_attribute` -> `Node.base.attributes.get`
* `Node.set_attribute` -> `Node.base.attributes.set`
* `Node.get_extra` -> `Node.base.extras.get`
* `Node.set_extra` -> `Node.base.extras.set`
* `Node.get_object_content` -> `Node.base.repository.get_object_content`
* `Node.add_incoming` -> `Node.base.links.add_incoming`

Due to the updated requirements of `click`, the `sphinx-click`
dependency of the `docs` extra also had to be upgraded because the lower
versions had an upper limit on `click`.
  • Loading branch information
sphuber committed Apr 28, 2022
1 parent e0c599f commit cd086dc
Show file tree
Hide file tree
Showing 19 changed files with 115 additions and 104 deletions.
35 changes: 13 additions & 22 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: continuous-integration
name: ci

on: [push, pull_request]

Expand All @@ -11,8 +11,7 @@ jobs:
steps:
- uses: actions/checkout@v2

- name: Cache python dependencies
id: cache-pip
- name: Cache Python dependencies
uses: actions/cache@v1
with:
path: ~/.cache/pip
Expand All @@ -25,13 +24,11 @@ jobs:
with:
python-version: '3.9'

- name: Install python dependencies
run:
pip install -e .[pre-commit,tests]
- name: Install Python dependencies
run: pip install -e .[pre-commit,tests]

- name: Run pre-commit
run:
pre-commit run --all-files || ( git status --short ; git diff ; exit 1 )
run: pre-commit run --all-files || ( git status --short ; git diff ; exit 1 )

tests:

Expand All @@ -43,6 +40,8 @@ jobs:
python-version: ['3.8', '3.9', '3.10']

services:
postgres:
image: postgres:12
rabbitmq:
image: rabbitmq:latest
ports:
Expand All @@ -51,8 +50,7 @@ jobs:
steps:
- uses: actions/checkout@v2

- name: Cache python dependencies
id: cache-pip
- name: Cache Python dependencies
uses: actions/cache@v1
with:
path: ~/.cache/pip
Expand All @@ -65,17 +63,10 @@ jobs:
with:
python-version: ${{ matrix.python-version }}

- name: Install system dependencies
run: |
sudo apt update
sudo apt install postgresql
- name: Install python dependencies
run: |
pip install --upgrade setuptools
pip install -e .[tests]
reentry scan
- name: Install Python dependencies
run: pip install -e .[tests]

- name: Run pytest
run:
pytest -sv tests
env:
AIIDA_WARN_v3: True
run: pytest -sv tests
6 changes: 0 additions & 6 deletions aiida_pseudo/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
# -*- coding: utf-8 -*-
# pylint: disable=wrong-import-position,wildcard-import
"""Module for the command line interface."""
import click_completion

# Activate the completion of parameter types provided by the click_completion package
click_completion.init()

from .family import cmd_family
from .install import cmd_install, cmd_install_family, cmd_install_pseudo_dojo, cmd_install_sssp
from .list import cmd_list
Expand Down
4 changes: 2 additions & 2 deletions aiida_pseudo/cli/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ def cmd_install_sssp(version, functional, protocol, download_only, traceback):

for element, values in metadata.items():
if family.get_pseudo(element).md5 != values['md5']:
Group.objects.delete(family.pk)
Group.collection.delete(family.pk)
msg = f"md5 of pseudo for element {element} does not match that of the metadata {values['md5']}"
echo.echo_critical(msg)

Expand Down Expand Up @@ -345,7 +345,7 @@ def cmd_install_pseudo_dojo(

for element, md5 in md5s.items():
if family.get_pseudo(element).md5 != md5:
Group.objects.delete(family.pk)
Group.collection.delete(family.pk)
msg = f'md5 of pseudo for element {element} does not match that of the metadata {md5}'
echo.echo_critical(msg)

Expand Down
4 changes: 2 additions & 2 deletions aiida_pseudo/cli/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def cmd_list(project, raw, family_type):
}

if get_families_builder().count() == 0:
echo.echo_info('no pseudo potential families have been installed yet: use `aiida-pseudo install`.')
echo.echo_report('no pseudo potential families have been installed yet: use `aiida-pseudo install`.')
return

rows = []
Expand All @@ -61,7 +61,7 @@ def cmd_list(project, raw, family_type):
rows.append(row)

if not rows:
echo.echo_info('no pseudo potential families found that match the filtering criteria.')
echo.echo_report('no pseudo potential families found that match the filtering criteria.')
return

if raw:
Expand Down
2 changes: 1 addition & 1 deletion aiida_pseudo/cli/params/arguments.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""Reusable arguments for CLI commands."""
from aiida.cmdline.params.arguments import OverridableArgument
from aiida.cmdline.params.arguments.overridable import OverridableArgument

from .types import PseudoPotentialFamilyParam

Expand Down
40 changes: 38 additions & 2 deletions aiida_pseudo/cli/root.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,43 @@
import click


class VerbosityGroup(click.Group):
"""Custom command group that automatically adds the ``VERBOSITY`` option to all subcommands."""

@staticmethod
def add_verbosity_option(cmd):
"""Apply the ``verbosity`` option to the command, which is common to all ``verdi`` commands."""
if 'verbosity' not in [param.name for param in cmd.params]:
cmd = options.VERBOSITY()(cmd)

return cmd

def group(self, *args, **kwargs):
"""Ensure that sub command groups use the same class but do not override an explicitly set value."""
kwargs.setdefault('cls', self.__class__)
return super().group(*args, **kwargs)

def get_command(self, ctx, cmd_name):
"""Return the command that corresponds to the requested ``cmd_name``.
This method is overridden from the base class in order to automatically add the verbosity option.
Note that if the command is not found and ``resilient_parsing`` is set to True on the context, then the latter
feature is disabled because most likely we are operating in tab-completion mode.
"""
cmd = super().get_command(ctx, cmd_name)

if cmd is not None:
return self.add_verbosity_option(cmd)

if ctx.resilient_parsing:
return None

return ctx.fail(f'`{cmd_name}` is not a {self.name} command.')


@click.group('aiida-pseudo', context_settings={'help_option_names': ['-h', '--help']})
@options.PROFILE(type=types.ProfileParamType(load_profile=True))
def cmd_root(profile): # pylint: disable=unused-argument
@options.PROFILE(type=types.ProfileParamType(load_profile=True), expose_value=False)
@options.VERBOSITY()
def cmd_root():
"""CLI for the ``aiida-pseudo`` plugin."""
6 changes: 3 additions & 3 deletions aiida_pseudo/cli/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ def attempt(message, exception_types=Exception, include_traceback=False):
import sys
import traceback

echo.echo_info(message, nl=False)
echo.echo_report(message, nl=False)

try:
yield
except exception_types as exception: # pylint: disable=broad-except
echo.echo_highlight(' [FAILED]', color='error', bold=True)
echo.echo(' [FAILED]', fg='red', bold=True)
message = str(exception)
if include_traceback:
message += f"\n{''.join(traceback.format_exception(*sys.exc_info()))}"
echo.echo_critical(message)
else:
echo.echo_highlight(' [OK]', color='success', bold=True)
echo.echo(' [OK]', fg='green', bold=True)


def create_family_from_archive(cls, label, filepath_archive: Path, fmt=None, pseudo_type=None):
Expand Down
16 changes: 7 additions & 9 deletions aiida_pseudo/data/pseudo/pseudo.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
__all__ = ('PseudoPotentialData',)


class PseudoPotentialData(plugins.DataFactory('singlefile')):
class PseudoPotentialData(plugins.DataFactory('core.singlefile')):
"""Base class for data types representing pseudo potentials."""

_key_element = 'element'
Expand All @@ -34,11 +34,9 @@ def get_or_create(cls, source: typing.Union[str, pathlib.Path, typing.BinaryIO],
query = orm.QueryBuilder()
query.append(cls, subclassing=False, filters={f'attributes.{cls._key_md5}': md5_from_filelike(source)})

existing = query.first()
pseudo = query.first(flat=True)

if existing:
pseudo = existing[0] # pylint: disable=unsubscriptable-object
else:
if not pseudo:
source.seek(0)
pseudo = cls(source, filename)

Expand Down Expand Up @@ -155,7 +153,7 @@ def element(self) -> typing.Optional[int]:
:return: the symbol of the element following the IUPAC naming standard or None if not defined.
"""
return self.get_attribute(self._key_element, None)
return self.base.attributes.get(self._key_element, None)

@element.setter
def element(self, value: str):
Expand All @@ -165,15 +163,15 @@ def element(self, value: str):
:raises ValueError: if the element symbol is invalid.
"""
self.validate_element(value)
self.set_attribute(self._key_element, value)
self.base.attributes.set(self._key_element, value)

@property
def md5(self) -> typing.Optional[int]:
"""Return the md5.
:return: the md5 of the stored file.
"""
return self.get_attribute(self._key_md5, None)
return self.base.attributes.get(self._key_md5, None)

@md5.setter
def md5(self, value: str):
Expand All @@ -183,4 +181,4 @@ def md5(self, value: str):
:raises ValueError: if the md5 does not match that of the currently stored file.
"""
self.validate_md5(value)
self.set_attribute(self._key_md5, value)
self.base.attributes.set(self._key_md5, value)
4 changes: 2 additions & 2 deletions aiida_pseudo/data/pseudo/upf.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def z_valence(self) -> typing.Optional[int]:
:return: the Z valence.
"""
return self.get_attribute(self._key_z_valence, None)
return self.base.attributes.get(self._key_z_valence, None)

@z_valence.setter
def z_valence(self, value: int):
Expand All @@ -107,4 +107,4 @@ def z_valence(self, value: int):
if not isinstance(value, int) or value < 0:
raise ValueError(f'`{value}` is not a positive integer')

self.set_attribute(self._key_z_valence, value)
self.base.attributes.set(self._key_z_valence, value)
8 changes: 4 additions & 4 deletions aiida_pseudo/data/pseudo/vps.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def z_valence(self) -> typing.Optional[int]:
:return: the Z valence.
"""
return self.get_attribute(self._key_z_valence, None)
return self.base.attributes.get(self._key_z_valence, None)

@z_valence.setter
def z_valence(self, value: int):
Expand All @@ -147,15 +147,15 @@ def z_valence(self, value: int):
if not isinstance(value, int) or value < 0:
raise ValueError(f'`{value}` is not a positive integer.')

self.set_attribute(self._key_z_valence, value)
self.base.attributes.set(self._key_z_valence, value)

@property
def xc_type(self) -> typing.Optional[int]:
"""Return the exchange-correlation type.
:return: the exchange-correlation type.
"""
return self.get_attribute(self._key_xc_type, None)
return self.base.attributes.get(self._key_xc_type, None)

@xc_type.setter
def xc_type(self, value: str):
Expand All @@ -167,4 +167,4 @@ def xc_type(self, value: str):
if not isinstance(value, str) or value not in VALID_XC_TYPES:
raise ValueError(f'`{value}` is not a valid OpenMX XcType string.')

self.set_attribute(self._key_xc_type, value)
self.base.attributes.set(self._key_xc_type, value)
8 changes: 4 additions & 4 deletions aiida_pseudo/groups/family/pseudo.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

__all__ = ('PseudoPotentialFamily',)

StructureData = DataFactory('structure')
StructureData = DataFactory('core.structure')


class PseudoPotentialFamily(Group):
Expand Down Expand Up @@ -172,7 +172,7 @@ def create_from_folder(cls, dirpath, label, *, description='', pseudo_type=None,
"""
type_check(description, str, allow_none=True)

if cls.objects.count(filters={'label': label}):
if cls.collection.count(filters={'label': label}):
raise ValueError(f'the {cls.__name__} `{label}` already exists')

family = cls(label=label, description=description)
Expand All @@ -191,7 +191,7 @@ def pseudo_type(self):
:return: the pseudopotential type or ``None`` if none has been set yet.
"""
return self.get_extra(self._key_pseudo_type, None)
return self.base.extras.get(self._key_pseudo_type, None)

def update_pseudo_type(self):
"""Update the pseudo type, stored as an extra, based on the current nodes in the family."""
Expand All @@ -203,7 +203,7 @@ def update_pseudo_type(self):
else:
entry_point_name = None

self.set_extra(self._key_pseudo_type, entry_point_name)
self.base.extras.set(self._key_pseudo_type, entry_point_name)

def add_nodes(self, nodes):
"""Add a node or a set of nodes to the family.
Expand Down
Loading

0 comments on commit cd086dc

Please sign in to comment.