Skip to content

Commit

Permalink
Merge branch 'master' into Parsing_zval_Psf_Psml
Browse files Browse the repository at this point in the history
  • Loading branch information
sphuber committed Apr 30, 2022
2 parents 9b3cbc9 + d8125f6 commit a36edaf
Show file tree
Hide file tree
Showing 18 changed files with 133 additions and 162 deletions.
8 changes: 4 additions & 4 deletions .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ version: 2
python:
version: 3.8
install:
- method: pip
path: .
extra_requirements:
- docs
- method: pip
path: .
extra_requirements:
- docs

sphinx:
builder: html
Expand Down
17 changes: 4 additions & 13 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,15 @@
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Path setup --------------------------------------------------------------

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys

sys.path.insert(0, os.path.abspath('../../'))

import aiida_pseudo

# -- Project information -----------------------------------------------------

project = 'aiida-pseudo'
copyright = '2020-2021, ECOLE POLYTECHNIQUE FEDERALE DE LAUSANNE (Theory and Simulation of Materials (THEOS) and National Centre for Computational Design and Discovery of Novel Materials (NCCR MARVEL)), Switzerland'
copyright = """\
2020-2022, ECOLE POLYTECHNIQUE FEDERALE DE LAUSANNE (Theory and Simulation of Materials (THEOS) and National Centre
for Computational Design and Discovery of Novel Materials (NCCR MARVEL)), Switzerland
"""
release = aiida_pseudo.__version__

# -- General configuration ---------------------------------------------------
Expand Down
6 changes: 0 additions & 6 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,6 @@ minversion = '6.0'
testpaths = [
'tests',
]
filterwarnings = [
'ignore::DeprecationWarning:distutils:',
'ignore::DeprecationWarning:frozendict:',
'ignore::DeprecationWarning:sqlalchemy_utils:',
'ignore::DeprecationWarning:pkg_resources:',
]

[tool.yapf]
align_closing_bracket_with_visual_indent = true
Expand Down
2 changes: 1 addition & 1 deletion src/aiida_pseudo/cli/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def cmd_install():


@cmd_install.command('family')
@click.argument('archive', type=types.PathOrUrl(exists=True, file_okay=True))
@click.argument('archive', type=types.PathOrUrl(exists=True, file_okay=True, path_type=pathlib.Path))
@click.argument('label', type=click.STRING)
@options_core.DESCRIPTION(help='Description for the family.')
@options.ARCHIVE_FORMAT()
Expand Down
5 changes: 2 additions & 3 deletions src/aiida_pseudo/cli/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,12 @@ def create_family_from_archive(cls, label, filepath_archive: Path, fmt=None, pse
with tempfile.TemporaryDirectory() as dirpath:

try:
# In Python 3.6 the ``unpack_archive`` method does not yet support ``pathlib.Path`` objects.
shutil.unpack_archive(str(filepath_archive), dirpath, format=fmt)
shutil.unpack_archive(filepath_archive, dirpath, format=fmt)
except shutil.ReadError as exception:
raise OSError(f'failed to unpack the archive `{filepath_archive}`: {exception}') from exception

try:
family = cls.create_from_folder(dirpath, label, pseudo_type=pseudo_type)
family = cls.create_from_folder(Path(dirpath), label, pseudo_type=pseudo_type)
except ValueError as exception:
raise OSError(f'failed to parse pseudos from `{dirpath}`: {exception}') from exception

Expand Down
18 changes: 9 additions & 9 deletions src/aiida_pseudo/groups/family/pseudo.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
"""Subclass of ``Group`` that serves as a base class for representing pseudo potential families."""
import os
import re
from typing import List, Mapping, Tuple, Union

Expand Down Expand Up @@ -77,13 +76,13 @@ def _validate_dirpath(cls, dirpath):
:return: the directory path to be used.
"""
if not os.path.isdir(dirpath):
if not dirpath.is_dir():
raise ValueError(f'`{dirpath}` is not a directory')

dirpath_contents = os.listdir(dirpath)
dirpath_contents = list(dirpath.iterdir())

if len(dirpath_contents) == 1 and os.path.isdir(os.path.join(dirpath, dirpath_contents[0])):
dirpath = os.path.join(dirpath, dirpath_contents[0])
if len(dirpath_contents) == 1 and (dirpath / dirpath_contents[0]).is_dir():
dirpath = dirpath_contents[0]

return dirpath

Expand Down Expand Up @@ -115,11 +114,12 @@ def parse_pseudos_from_directory(cls, dirpath, pseudo_type=None, deduplicate=Tru
dirpath = cls._validate_dirpath(dirpath)
pseudo_type = cls._validate_pseudo_type(pseudo_type)

for filename in os.listdir(dirpath):
filepath = os.path.join(dirpath, filename)
for filepath in dirpath.iterdir():

if not os.path.isfile(filepath):
raise ValueError(f'dirpath `{dirpath}` contains at least one entry that is not a file')
filename = filepath.name

if not filepath.is_file():
raise ValueError(f'dirpath `{dirpath}` contains at least one entry that is not a file: {filepath}')

with open(filepath, 'rb') as handle:
try:
Expand Down
27 changes: 10 additions & 17 deletions src/aiida_pseudo/groups/family/pseudo_dojo.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# -*- coding: utf-8 -*-
"""Subclass of `PseudoPotentialFamily` designed to represent a PseudoDojo configuration."""
import json
import os
from pathlib import Path
import pathlib
import re
from typing import NamedTuple, Sequence
import warnings
Expand Down Expand Up @@ -247,7 +246,7 @@ def get_cutoffs_from_djrepo(cls, djrepo, pseudo_type):
return cutoffs

@classmethod
def parse_djrepos_from_folder(cls, dirpath, pseudo_type):
def parse_djrepos_from_folder(cls, dirpath: pathlib.Path, pseudo_type):
# pylint: disable=too-many-locals,too-many-branches
"""Parse the djrepo files in the given directory into a list of data nodes.
Expand All @@ -265,19 +264,14 @@ def parse_djrepos_from_folder(cls, dirpath, pseudo_type):
cutoffs = {'low': {}, 'normal': {}, 'high': {}}
elements = []

if not os.path.isdir(dirpath):
raise ValueError(f'`{dirpath}` is not a directory')
dirpath = cls._validate_dirpath(dirpath)

dirpath_contents = os.listdir(dirpath)
for filepath in dirpath.iterdir():

if len(dirpath_contents) == 1 and os.path.isdir(os.path.join(dirpath, dirpath_contents[0])):
dirpath = os.path.join(dirpath, dirpath_contents[0])
filename = filepath.name

for filename in os.listdir(dirpath):
filepath = os.path.join(dirpath, filename)

if not os.path.isfile(filepath):
raise ValueError(f'dirpath `{dirpath}` contains at least one entry that is not a file')
if not filepath.is_file():
raise ValueError(f'dirpath `{dirpath}` contains at least one entry that is not a file: {filepath}')

# Some of the djrepo archives contain extraneous files. Here we skip files with unsupported extensions.
if filename.split('.')[-1] not in cls._pseudo_repo_file_extensions:
Expand Down Expand Up @@ -325,7 +319,7 @@ def parse_djrepos_from_folder(cls, dirpath, pseudo_type):
return md5s, cutoffs

@classmethod
def parse_djrepos_from_archive(cls, filepath_metadata: Path, fmt=None, pseudo_type=None):
def parse_djrepos_from_archive(cls, filepath_metadata: pathlib.Path, fmt=None, pseudo_type=None):
"""Parse metadata from a djrepo .tgz archive.
.. warning:: the archive should not contain any subdirectories, but just the djrepo files.
Expand All @@ -344,15 +338,14 @@ def parse_djrepos_from_archive(cls, filepath_metadata: Path, fmt=None, pseudo_ty

with tempfile.TemporaryDirectory() as dirpath:
try:
# In Python 3.6 the ``unpack_archive`` method does not yet support ``pathlib.Path`` objects.
shutil.unpack_archive(str(filepath_metadata), dirpath, format=fmt)
shutil.unpack_archive(filepath_metadata, dirpath, format=fmt)
except shutil.ReadError as exception:
raise OSError(
f'failed to unpack the metadata archive `{filepath_metadata}`: {exception}'
) from exception

try:
md5s, cutoffs = cls.parse_djrepos_from_folder(dirpath, pseudo_type=pseudo_type)
md5s, cutoffs = cls.parse_djrepos_from_folder(pathlib.Path(dirpath), pseudo_type=pseudo_type)
except ValueError as exception:
raise OSError(f'failed to parse djrepos from `{dirpath}`: {exception}') from exception

Expand Down
30 changes: 15 additions & 15 deletions tests/cli/test_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@


@pytest.fixture
def run_monkeypatched_install_sssp(run_cli_command, get_pseudo_potential_data, monkeypatch, tmpdir):
def run_monkeypatched_install_sssp(run_cli_command, get_pseudo_potential_data, monkeypatch, tmp_path):
"""Fixture to monkeypatch the ``aiida_pseudo.cli.install.download_sssp`` method and call the install cmd."""

def download_sssp(
Expand All @@ -37,14 +37,14 @@ def download_sssp(

element = 'Ar'
pseudo = get_pseudo_potential_data(element)
filepath = tmpdir / pseudo.filename
filepath = tmp_path / pseudo.filename

with pseudo.open(mode='rb') as handle:
md5 = hashlib.md5(handle.read()).hexdigest()
handle.seek(0)
filepath.write_binary(handle.read())
filepath.write_bytes(handle.read())

filename_archive = shutil.make_archive('temparchive', 'gztar', root_dir=tmpdir, base_dir='.')
filename_archive = shutil.make_archive('temparchive', 'gztar', root_dir=tmp_path, base_dir='.')
shutil.move(pathlib.Path.cwd() / filename_archive, filepath_archive)

with open(filepath_metadata, 'w', encoding='utf-8') as handle:
Expand All @@ -60,7 +60,7 @@ def _run_monkeypatched_install_sssp(options=None, raises=None):


@pytest.fixture
def run_monkeypatched_install_pseudo_dojo(run_cli_command, get_pseudo_potential_data, monkeypatch, tmpdir):
def run_monkeypatched_install_pseudo_dojo(run_cli_command, get_pseudo_potential_data, monkeypatch, tmp_path):
"""Fixture to monkeypatch the ``aiida_pseudo.cli.install.download_pseudo_dojo`` method and call the install cmd."""

def download_pseudo_dojo(
Expand All @@ -82,25 +82,25 @@ def download_pseudo_dojo(

element = 'Ar'
pseudo = get_pseudo_potential_data(element, entry_point='jthxml')
filepath = tmpdir / pseudo.filename
filepath = tmp_path / pseudo.filename

with pseudo.open(mode='rb') as handle:
md5 = hashlib.md5(handle.read()).hexdigest()
handle.seek(0)
filepath.write_binary(handle.read())
filepath.write_bytes(handle.read())

filename_archive = shutil.make_archive('temparchive', 'gztar', root_dir=tmpdir, base_dir='.')
filename_archive = shutil.make_archive('temparchive', 'gztar', root_dir=tmp_path, base_dir='.')
shutil.move(pathlib.Path.cwd() / filename_archive, filepath_archive)

data = {'hints': {'high': {'ecut': 20.00}, 'low': {'ecut': 20.00}, 'normal': {'ecut': 20.00}}, 'md5': md5}

filepath_djrepo = tmpdir / f'{element}.djrepo'
filepath_djrepo = tmp_path / f'{element}.djrepo'

with open(filepath_djrepo, 'w', encoding='utf-8') as handle:
json.dump(data, handle)
handle.flush()

filename_metadata = shutil.make_archive('tempmetadata', 'gztar', root_dir=tmpdir, base_dir='.')
filename_metadata = shutil.make_archive('tempmetadata', 'gztar', root_dir=tmp_path, base_dir='.')
shutil.move(pathlib.Path.cwd() / filename_metadata, filepath_metadata)

def _run_monkeypatched_install_pseudo_dojo(options=None, raises=None):
Expand Down Expand Up @@ -134,7 +134,7 @@ def test_install_family_folder(run_cli_command, filepath_pseudos):
label = 'family_test'
description = 'description'
dirpath = filepath_pseudos()
options = ['-D', description, dirpath, label]
options = ['-D', description, str(dirpath), label]

result = run_cli_command(cmd_install_family, options)
assert f'installed `{label}`' in result.output
Expand Down Expand Up @@ -269,7 +269,7 @@ def test_install_pseudo_dojo_monkeypatched(run_monkeypatched_install_pseudo_dojo
assert family.label == label


@pytest.mark.usefixtures('clear_db', 'chtmpdir')
@pytest.mark.usefixtures('clear_db', 'chdir_tmp_path')
def test_install_sssp_download_only(run_monkeypatched_install_sssp):
"""Test the ``aiida-pseudo install sssp`` command with the ``--download-only`` option."""
options = ['--download-only']
Expand All @@ -279,7 +279,7 @@ def test_install_sssp_download_only(run_monkeypatched_install_sssp):
assert 'written to the current directory.' in result.output


@pytest.mark.usefixtures('clear_db', 'chtmpdir')
@pytest.mark.usefixtures('clear_db', 'chdir_tmp_path')
def test_install_sssp_download_only_exists(run_monkeypatched_install_sssp, get_pseudo_family):
"""Test the ``aiida-pseudo install sssp`` command with the ``--download-only`` option.
Expand All @@ -300,7 +300,7 @@ def test_install_sssp_download_only_exists(run_monkeypatched_install_sssp, get_p
assert 'written to the current directory.' in result.output


@pytest.mark.usefixtures('clear_db', 'chtmpdir')
@pytest.mark.usefixtures('clear_db', 'chdir_tmp_path')
def test_install_pseudo_dojo_download_only(run_monkeypatched_install_pseudo_dojo):
"""Test the ``aiida-pseudo install pseudo-dojo`` command with the ``--download-only`` option."""
options = ['--download-only']
Expand All @@ -310,7 +310,7 @@ def test_install_pseudo_dojo_download_only(run_monkeypatched_install_pseudo_dojo
assert 'written to the current directory.' in result.output


@pytest.mark.usefixtures('clear_db', 'chtmpdir')
@pytest.mark.usefixtures('clear_db', 'chdir_tmp_path')
def test_install_pseudo_dojo_download_only_exists(run_monkeypatched_install_pseudo_dojo, get_pseudo_family):
"""Test the ``aiida-pseudo install pseudo_dojo`` command with the ``--download-only`` option.
Expand Down
8 changes: 4 additions & 4 deletions tests/cli/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,19 @@ def test_create_family_from_archive(get_pseudo_archive, fmt):


@pytest.mark.usefixtures('clear_db')
def test_create_family_from_archive_incorrect_filetype(tmpdir):
def test_create_family_from_archive_incorrect_filetype(tmp_path):
"""Test the `create_family_from_archive` utility function for incorrect archive filetype."""
with pytest.raises(OSError, match=r'failed to unpack the archive.*'):
create_family_from_archive(PseudoPotentialFamily, 'label', str(tmpdir))
create_family_from_archive(PseudoPotentialFamily, 'label', tmp_path)


@pytest.mark.usefixtures('clear_db')
def test_create_family_from_archive_incorrect_format(tmpdir):
def test_create_family_from_archive_incorrect_format(tmp_path):
"""Test the `create_family_from_archive` utility function for invalid archive content."""
with tempfile.NamedTemporaryFile(suffix='.tar.gz') as filepath_archive:

with tarfile.open(filepath_archive.name, 'w:gz') as tar:
tar.add(str(tmpdir), arcname='.')
tar.add(tmp_path, arcname='.')

with pytest.raises(OSError, match=r'failed to parse pseudos from.*'):
create_family_from_archive(PseudoPotentialFamily, 'label', filepath_archive.name)
Expand Down
Loading

0 comments on commit a36edaf

Please sign in to comment.