Skip to content

Commit

Permalink
Drop Python 2 support
Browse files Browse the repository at this point in the history
The following commands were executed to clean all source files:

    sed -i '/from __future__.*$/d' {} +
    sed -i 's/(object):/:/g' {} +
    sed -i 's/super([^)]*,[^)]*)/super()/g' {} +
    sed -i '/\(import six\|from six\).*$/d' {} +
    sed -i '/\(six\.add_metaclass\).*$/d' {} +
    sed -i 's/six.integer_types/int/g' {} +
    sed -i 's/six.string_types/str/g' {} +
    sed -i 's/six.text_type/str/g' {} +
    sed -i 's/six.binary_type/bytes/g' {} +
    sed -i 's/six.moves.StringIO/io.StringIO/g' {} +
    sed -i 's/six.StringIO/io.StringIO/g' {} +
    sed -i 's/six.moves.BytesIO/io.BytesIO/g' {} +
    sed -i 's/six.BytesIO/io.BytesIO/g' {} +
    sed -i 's/six.moves.range/range/g' {} +
    sed -i 's|six.iterkeys(\([^)]*\))|\1.keys()|' {} +
    sed -i 's|six.iteritems(\([^)]*\))|\1.items()|' {} +
    sed -i 's|six.itervalues(\([^)]*\))|\1.values()|' {} +

The operations were applied to all files using `find -exec`:

    find . -type f -not -path './.git*' -exec

Note the exclusion of the `.git` folder which is very important.
  • Loading branch information
sphuber committed May 7, 2020
1 parent 4ffdddd commit d543396
Show file tree
Hide file tree
Showing 131 changed files with 185 additions and 490 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ jobs:

strategy:
matrix:
python-version: [2.7, 3.5, 3.6, 3.7, 3.8]
python-version: [3.5, 3.6, 3.7, 3.8]

services:
postgres:
Expand Down Expand Up @@ -111,7 +111,6 @@ jobs:
- name: Install python dependencies
run: |
pip install --upgrade setuptools
pip install numpy==1.16.4
pip install -e .[dev]
reentry scan
Expand Down
13 changes: 0 additions & 13 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,3 @@ repos:
./utils/validate_version_number.py|
)$
pass_filenames: false

- repo: https://github.com/python-modernize/python-modernize.git
rev: a234ce4e185cf77a55632888f1811d83b4ad9ef2
hooks:
- id: python-modernize
exclude: >
(?x)^(
docs/.*|
examples/.*
)$
args:
- --write
- --nobackups
4 changes: 1 addition & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
## v3.0.0:

**TODO**
## v4.0.0:

## v2.1.0:
Minor release adding a new feature, fixing a critical bug in `PwParser` and reducing the size of the package
Expand Down
22 changes: 9 additions & 13 deletions aiida_quantumespresso/calculations/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
# -*- coding: utf-8 -*-
"""Base `CalcJob` for implementations for pw.x and cp.x of Quantum ESPRESSO."""
from __future__ import absolute_import

import abc
import os
import six
from six.moves import zip

from aiida import orm
from aiida.common import datastructures, exceptions
Expand Down Expand Up @@ -68,9 +64,9 @@ def xml_filepaths(cls): # pylint: disable=no-self-argument
@classmethod
def define(cls, spec):
# yapf: disable
super(BasePwCpInputGenerator, cls).define(spec)
spec.input('metadata.options.input_filename', valid_type=six.string_types, default=cls._DEFAULT_INPUT_FILE)
spec.input('metadata.options.output_filename', valid_type=six.string_types, default=cls._DEFAULT_OUTPUT_FILE)
super().define(spec)
spec.input('metadata.options.input_filename', valid_type=str, default=cls._DEFAULT_INPUT_FILE)
spec.input('metadata.options.output_filename', valid_type=str, default=cls._DEFAULT_OUTPUT_FILE)
spec.input('metadata.options.withmpi', valid_type=bool, default=True) # Override default withmpi=False
spec.input('structure', valid_type=orm.StructureData,
help='The input structure.')
Expand Down Expand Up @@ -183,7 +179,7 @@ def prepare_for_submission(self, folder):

with folder.open(self._ENVIRON_INPUT_FILE_NAME, 'w') as handle:
handle.write('&ENVIRON\n')
for key, value in sorted(six.iteritems(environ_namelist)):
for key, value in sorted(environ_namelist.items()):
handle.write(convert_input_to_namelist_entry(key, value, mapping=mapping_species))
handle.write('/\n')

Expand Down Expand Up @@ -255,7 +251,7 @@ def _generate_PWCPinputdata(cls, parameters, settings, pseudos, structure, kpoin
# and the second-level keys as lowercase
# (deeper levels are unchanged)
input_params = _uppercase_dict(parameters.get_dict(), dict_name='parameters')
input_params = {k: _lowercase_dict(v, dict_name=k) for k, v in six.iteritems(input_params)}
input_params = {k: _lowercase_dict(v, dict_name=k) for k, v in input_params.items()}

# I remove unwanted elements (for the moment, instead, I stop; to change when we setup a reasonable logging)
for blocked in cls._blocked_keywords:
Expand Down Expand Up @@ -559,14 +555,14 @@ def _generate_PWCPinputdata(cls, parameters, settings, pseudos, structure, kpoin
"namelists using the NAMELISTS inside the 'settings' input "
'node'.format(calculation_type))

inputfile = u''
inputfile = ''
for namelist_name in namelists_toprint:
inputfile += u'&{0}\n'.format(namelist_name)
inputfile += '&{0}\n'.format(namelist_name)
# namelist content; set to {} if not present, so that we leave an empty namelist
namelist = input_params.pop(namelist_name, {})
for key, value in sorted(namelist.items()):
inputfile += convert_input_to_namelist_entry(key, value, mapping=mapping_species)
inputfile += u'/\n'
inputfile += '/\n'

# Write cards now
inputfile += atomic_species_card
Expand Down Expand Up @@ -608,7 +604,7 @@ def _case_transform_dict(dictionary, dict_name, func_name, transform):

if not isinstance(dictionary, dict):
raise TypeError('{} accepts only dictionaries as argument, got {}'.format(func_name, type(dictionary)))
new_dict = dict((transform(str(k)), v) for k, v in six.iteritems(dictionary))
new_dict = dict((transform(str(k)), v) for k, v in dictionary.items())
if len(new_dict) != len(dictionary):
num_items = Counter(transform(str(k)) for k in dictionary.keys())
double_keys = ','.join([k for k, v in num_items if v > 1])
Expand Down
6 changes: 2 additions & 4 deletions aiida_quantumespresso/calculations/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
The custom `CalcJob` base class automatically sets the `invalidates_cache` attribute of exit codes based on the status
integer. All `CalcJob` implementations in `aiida-quantumespresso` must use this base class, not `aiida.engine.CalcJob`.
"""
from __future__ import absolute_import

from aiida.engine import CalcJob as _BaseCalcJob
from aiida.engine.processes.process_spec import CalcJobProcessSpec as _BaseCalcJobProcessSpec

Expand Down Expand Up @@ -37,7 +35,7 @@ def exit_code(self, status, label, message, invalidates_cache=None):
super(CalcJobProcessSpec,
self).exit_code(status=status, label=label, message=message, invalidates_cache=invalidates_cache)
except TypeError: # For AiiDA version <1.1
super(CalcJobProcessSpec, self).exit_code(status=status, message=message, label=label)
super().exit_code(status=status, message=message, label=label)


class CalcJob(_BaseCalcJob): # pylint: disable=abstract-method
Expand All @@ -48,5 +46,5 @@ class CalcJob(_BaseCalcJob): # pylint: disable=abstract-method
@classmethod
def define(cls, spec):
# yapf: disable
super(CalcJob, cls).define(spec)
super().define(spec)
spec.inputs['metadata']['options']['resources'].default = lambda: {'num_machines': 1}
7 changes: 2 additions & 5 deletions aiida_quantumespresso/calculations/cp.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,8 @@
for development when new cards are needed
TODO: all a lot of logger.debug stuff
"""
from __future__ import absolute_import

import os

import six
from aiida import orm
from aiida.common.lang import classproperty

Expand Down Expand Up @@ -129,8 +126,8 @@ def xml_filepaths(cls):
@classmethod
def define(cls, spec):
# yapf: disable
super(CpCalculation, cls).define(spec)
spec.input('metadata.options.parser_name', valid_type=six.string_types, default='quantumespresso.cp')
super().define(spec)
spec.input('metadata.options.parser_name', valid_type=str, default='quantumespresso.cp')
spec.output('output_trajectory', valid_type=orm.TrajectoryData)
spec.output('output_parameters', valid_type=orm.Dict)
spec.default_output_node = 'output_parameters'
Expand Down
4 changes: 1 addition & 3 deletions aiida_quantumespresso/calculations/dos.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# -*- coding: utf-8 -*-
"""`CalcJob` implementation for the dos.x code of Quantum ESPRESSO."""
from __future__ import absolute_import

from aiida import orm
from aiida_quantumespresso.calculations.namelists import NamelistsCalculation

Expand All @@ -22,7 +20,7 @@ class DosCalculation(NamelistsCalculation):
@classmethod
def define(cls, spec):
# yapf: disable
super(DosCalculation, cls).define(spec)
super().define(spec)
spec.input('parent_folder', valid_type=(orm.RemoteData, orm.FolderData), required=True)
spec.output('output_parameters', valid_type=orm.Dict)
spec.output('output_dos', valid_type=orm.XyData)
Expand Down
23 changes: 9 additions & 14 deletions aiida_quantumespresso/calculations/epw.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
# -*- coding: utf-8 -*-
"""Plugin to create a Quantum Espresso epw.x input file."""
from __future__ import absolute_import

from __future__ import print_function
import os
import numpy as np
import six
from six.moves import range

from aiida import orm
from aiida.common import datastructures, exceptions
Expand Down Expand Up @@ -43,9 +38,9 @@ class EpwCalculation(CalcJob):
@classmethod
def define(cls, spec):
# yapf: disable
super(EpwCalculation, cls).define(spec)
spec.input('metadata.options.input_filename', valid_type=six.string_types, default=cls._DEFAULT_INPUT_FILE)
spec.input('metadata.options.output_filename', valid_type=six.string_types, default=cls._DEFAULT_OUTPUT_FILE)
super().define(spec)
spec.input('metadata.options.input_filename', valid_type=str, default=cls._DEFAULT_INPUT_FILE)
spec.input('metadata.options.output_filename', valid_type=str, default=cls._DEFAULT_OUTPUT_FILE)
spec.input('metadata.options.withmpi', valid_type=bool, default=True)
spec.input('kpoints', valid_type=orm.KpointsData, help='coarse kpoint mesh')
spec.input('qpoints', valid_type=orm.KpointsData, help='coarse qpoint mesh')
Expand Down Expand Up @@ -109,7 +104,7 @@ def test_offset(offset):

# I put the first-level keys as uppercase (i.e., namelist and card names) and the second-level keys as lowercase
parameters = _uppercase_dict(self.inputs.parameters.get_dict(), dict_name='parameters')
parameters = {k: _lowercase_dict(v, dict_name=k) for k, v in six.iteritems(parameters)}
parameters = {k: _lowercase_dict(v, dict_name=k) for k, v in parameters.items()}

if 'INPUTEPW' not in parameters:
raise exceptions.InputValidationError('required namelist INPUTEPW not specified')
Expand Down Expand Up @@ -188,18 +183,18 @@ def test_offset(offset):

# add here the list of point coordinates
if len(list_of_points) > 1:
postpend_text = u'{} cartesian\n'.format(len(list_of_points))
postpend_text = '{} cartesian\n'.format(len(list_of_points))
for points in list_of_points:
postpend_text += u'{0:18.10f} {1:18.10f} {2:18.10f} \n'.format(*points)
postpend_text += '{0:18.10f} {1:18.10f} {2:18.10f} \n'.format(*points)

with folder.open(self.metadata.options.input_filename, 'w') as infile:
for namelist_name in namelists_toprint:
infile.write(u'&{0}\n'.format(namelist_name))
infile.write('&{0}\n'.format(namelist_name))
# namelist content; set to {} if not present, so that we leave an empty namelist
namelist = parameters.pop(namelist_name, {})
for key, value in sorted(six.iteritems(namelist)):
for key, value in sorted(namelist.items()):
infile.write(convert_input_to_namelist_entry(key, value))
infile.write(u'/\n')
infile.write('/\n')

# add list of qpoints if required
if postpend_text is not None:
Expand Down
18 changes: 7 additions & 11 deletions aiida_quantumespresso/calculations/helpers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
# -*- coding: utf-8 -*-
"""Utilities to automatically format, convert and validate data structures from python to fortran."""
from __future__ import absolute_import
from __future__ import print_function

import copy
import difflib
import os
import xml.dom.minidom
from packaging.version import Version
import six

from aiida.common import InputValidationError, InternalError

Expand All @@ -34,19 +30,19 @@ def _check_and_convert(keyword, val, expected_type):
else:
raise TypeError('Expected a boolean for keyword {}, found {} instead'.format(keyword, type(val)))
elif expected_type.upper() == 'REAL':
if isinstance(val, six.integer_types):
if isinstance(val, int):
outval = float(val)
elif isinstance(val, float):
outval = val
else:
raise TypeError('Expected a float for keyword {}, found {} instead'.format(keyword, type(val)))
elif expected_type.upper() == 'INTEGER':
if isinstance(val, six.integer_types):
if isinstance(val, int):
outval = val
else:
raise TypeError('Expected an integer for keyword {}, found {} instead'.format(keyword, type(val)))
elif expected_type.upper() == 'CHARACTER':
if isinstance(val, six.string_types):
if isinstance(val, str):
outval = val
else:
raise TypeError('Expected a string for keyword {}, found {} instead'.format(keyword, type(val)))
Expand Down Expand Up @@ -139,13 +135,13 @@ def pw_input_helper(input_params, structure, stop_at_first_error=False, flat_mod
input_params_internal = {}
input_original_namelists = {}
all_input_namelists = set()
for namelist, content in six.iteritems(input_params):
for namelist, content in input_params.items():
if not isinstance(content, dict):
raise QEInputValidationError(
"The content associated to the namelist '{}' must be a dictionary".format(namelist)
)
all_input_namelists.add(namelist)
for key, value in six.iteritems(content):
for key, value in content.items():
input_params_internal[key] = copy.deepcopy(value)
if key in input_original_namelists:
err_str = "The keyword '{}' was specified both in the namelist {} and {}.".format(
Expand Down Expand Up @@ -382,7 +378,7 @@ def pw_input_helper(input_params, structure, stop_at_first_error=False, flat_mod
# the compulsory ones at the end
inserted_kws = []
# I parse each element of the input dictionary
for keyword, value in six.iteritems(input_params_internal):
for keyword, value in input_params_internal.items():
keyword = keyword.lower()

if keyword in valid_kws:
Expand Down Expand Up @@ -449,7 +445,7 @@ def pw_input_helper(input_params, structure, stop_at_first_error=False, flat_mod
continue

outdict = {}
for kindname, found_item in six.iteritems(value):
for kindname, found_item in value.items():
if kindname not in atomic_species_list:
err_str = "Error, '{}' is not a valid kind name.".format(kindname)
if stop_at_first_error:
Expand Down
10 changes: 4 additions & 6 deletions aiida_quantumespresso/calculations/matdyn.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# -*- coding: utf-8 -*-
"""`CalcJob` implementation for the matdyn.x code of Quantum ESPRESSO."""
from __future__ import absolute_import

from aiida import orm
from aiida_quantumespresso.calculations.namelists import NamelistsCalculation
from aiida_quantumespresso.data.force_constants import ForceConstantsData
Expand All @@ -28,7 +26,7 @@ class MatdynCalculation(NamelistsCalculation):
@classmethod
def define(cls, spec):
# yapf: disable
super(MatdynCalculation, cls).define(spec)
super().define(spec)
spec.input('force_constants', valid_type=ForceConstantsData, required=True)
spec.input('kpoints', valid_type=orm.KpointsData, help='Kpoints on which to calculate the phonon frequencies.')
spec.inputs.pop('parent_folder')
Expand All @@ -55,9 +53,9 @@ def _get_following_text(self):
except AttributeError:
kpoints = self.inputs.kpoints.get_kpoints_mesh(print_list=True)

kpoints_string = [u'{}'.format(len(kpoints))]
kpoints_string = ['{}'.format(len(kpoints))]
for kpoint in kpoints:
kpoints_string.append(u'{:18.10f} {:18.10f} {:18.10f}'.format(*kpoint))
kpoints_string.append('{:18.10f} {:18.10f} {:18.10f}'.format(*kpoint))

return '\n'.join(kpoints_string) + '\n'

Expand All @@ -70,7 +68,7 @@ def prepare_for_submission(self, folder):
force_constants = self.inputs.force_constants
self._blocked_keywords.append(('INPUT', 'flfrc', force_constants.filename))

calcinfo = super(MatdynCalculation, self).prepare_for_submission(folder)
calcinfo = super().prepare_for_submission(folder)
calcinfo.local_copy_list.append((force_constants.uuid, force_constants.filename, force_constants.filename))

return calcinfo
Loading

0 comments on commit d543396

Please sign in to comment.