Skip to content

Commit

Permalink
Run CI with two different uv resolution strategies: highest and `…
Browse files Browse the repository at this point in the history
…lowest-direct` (#3852)

* fix typing_extensions ImportError

#3752 (comment)

* bump min ase to 3.23.0

* test both lowest-direct and highest uv package resolutions in CI

* establish some loose lower bounds on all deps

needed for deps install with --resolution=lowest-direct to work

* netcdf4>=1.6

* pin chgnet==0.3.6

* try chgnet==0.3.5

* bump pre-commit hooks

* imperative doc strings

* doc str white space

* test_string->test_str

* ruff auto fixes

* matgl>=1.1.1 numba>=0.55

* try fix netcdf4 install

* h5py>=3.9.0

* monty>=2024.5.24

fixes TypeError: deprecated() got an unexpected keyword argument 'deadline'

* revert TestWavecar to again inherit from PymatgenTest

* h5py>=3.11.0

* phonopy>=2.23

* scipy>=1.13.0

* matplotlib>=3.8

* requests>=2.32

* don't run oldest/newest supported python twice on linux AND windows

* fix bad refactor in get_atom_map

fixes KeyError: 'Co' ipot = self.pot_dict[el.symbol]
  • Loading branch information
janosh authored Jun 3, 2024
1 parent 2982968 commit eccf075
Show file tree
Hide file tree
Showing 43 changed files with 179 additions and 233 deletions.
32 changes: 12 additions & 20 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,18 @@ jobs:
strategy:
fail-fast: false
matrix:
# maximize CI coverage of different platforms and python versions while minimizing the
# total number of jobs. We run all pytest splits with the oldest supported python
# version (currently 3.9) on windows (seems most likely to surface errors) and with
# newest version (currently 3.12) on ubuntu (to get complete coverage on unix). We
# ignore mac-os, which is assumed to be similar to ubuntu.
config:
- { os: windows-latest, python: "3.9", resolution: highest }
- { os: ubuntu-latest, python: "3.12", resolution: lowest-direct }
# pytest-split automatically distributes work load so parallel jobs finish in similar time
os: [ubuntu-latest, windows-latest]
python-version: ["3.9", "3.12"]
split: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# include/exclude is meant to maximize CI coverage of different platforms and python
# versions while minimizing the total number of jobs. We run all pytest splits with the
# oldest supported python version (currently 3.9) on windows (seems most likely to surface
# errors) and with newest version (currently 3.12) on ubuntu (to get complete and speedy
# coverage on unix). We ignore mac-os, which is assumed to be similar to ubuntu.
exclude:
- os: windows-latest
python-version: "3.12"
- os: ubuntu-latest
python-version: "3.9"

runs-on: ${{ matrix.os }}
runs-on: ${{ matrix.config.os }}

env:
PMG_MAPI_KEY: ${{ secrets.PMG_MAPI_KEY }}
Expand All @@ -55,13 +51,13 @@ jobs:

- name: Create mamba environment
run: |
micromamba create -n pmg python=${{ matrix.python-version }} --yes
micromamba create -n pmg python=${{ matrix.config.python }} --yes
- name: Install uv
run: micromamba run -n pmg pip install uv

- name: Install ubuntu-only conda dependencies
if: matrix.os == 'ubuntu-latest'
if: matrix.config.os == 'ubuntu-latest'
run: |
micromamba install -n pmg -c conda-forge enumlib packmol bader openbabel openff-toolkit --yes
Expand All @@ -73,11 +69,7 @@ jobs:
pip install torch
uv pip install numpy cython
uv pip install --editable '.[dev,optional]'
# TODO remove next line installing ase from main branch when FrechetCellFilter is released
uv pip install --upgrade 'git+https://gitlab.com/ase/ase'
uv pip install --editable '.[dev,optional]' --resolution=${{ matrix.config.resolution }}
- name: pytest split ${{ matrix.split }}
run: |
Expand Down
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ ci:

repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.4.3
rev: v0.4.7
hooks:
- id: ruff
args: [--fix, --unsafe-fixes]
Expand All @@ -27,7 +27,7 @@ repos:
- id: mypy

- repo: https://github.com/codespell-project/codespell
rev: v2.2.6
rev: v2.3.0
hooks:
- id: codespell
stages: [commit, commit-msg]
Expand All @@ -47,7 +47,7 @@ repos:
- id: blacken-docs

- repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.40.0
rev: v0.41.0
hooks:
- id: markdownlint
# MD013: line too long
Expand All @@ -64,6 +64,6 @@ repos:
args: [--drop-empty-cells, --keep-output]

- repo: https://github.com/RobertCraigie/pyright-python
rev: v1.1.361
rev: v1.1.365
hooks:
- id: pyright
8 changes: 4 additions & 4 deletions pymatgen/alchemy/materials.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ def from_cif_str(
TransformedStructure
"""
parser = CifParser.from_str(cif_string, occupancy_tolerance=occupancy_tolerance)
raw_string = re.sub(r"'", '"', cif_string)
raw_str = re.sub(r"'", '"', cif_string)
cif_dict = parser.as_dict()
cif_keys = list(cif_dict)
struct = parser.parse_structures(primitive=primitive)[0]
Expand All @@ -303,7 +303,7 @@ def from_cif_str(
source_info = {
"source": source,
"datetime": str(datetime.datetime.now()),
"original_file": raw_string,
"original_file": raw_str,
"cif_data": cif_dict[cif_keys[0]],
}
return cls(struct, transformations, history=[source_info])
Expand All @@ -326,12 +326,12 @@ def from_poscar_str(
raise ValueError(
"Transformation can be created only from POSCAR strings with proper VASP5 element symbols."
)
raw_string = re.sub(r"'", '"', poscar_string)
raw_str = re.sub(r"'", '"', poscar_string)
struct = poscar.structure
source_info = {
"source": "POSCAR",
"datetime": str(datetime.datetime.now()),
"original_file": raw_string,
"original_file": raw_str,
}
return cls(struct, transformations, history=[source_info])

Expand Down
10 changes: 5 additions & 5 deletions pymatgen/analysis/chemenv/connectivity/structure_connectivity.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,12 @@ def setup_environment_subgraph(self, environments_symbols, only_atoms=None):
if not isinstance(environments_symbols, collections.abc.Iterable):
environments_symbols = [environments_symbols]
environments_symbols = sorted(environments_symbols)
envs_string = "-".join(environments_symbols)
envs_str = "-".join(environments_symbols)
if only_atoms is not None:
envs_string += "#" + "-".join(sorted(only_atoms))
envs_str += "#" + "-".join(sorted(only_atoms))
# Get it directly if it was already computed
if envs_string in self.environment_subgraphs:
self._environment_subgraph = self.environment_subgraphs[envs_string]
if envs_str in self.environment_subgraphs:
self._environment_subgraph = self.environment_subgraphs[envs_str]
return

# Initialize graph for a subset of environments
Expand Down Expand Up @@ -248,7 +248,7 @@ def setup_environment_subgraph(self, environments_symbols, only_atoms=None):
delta=conn,
ligands=ligands,
)
self.environment_subgraphs[envs_string] = self._environment_subgraph
self.environment_subgraphs[envs_str] = self._environment_subgraph

def setup_connectivity_description(self):
pass
Expand Down
4 changes: 2 additions & 2 deletions pymatgen/analysis/elasticity/elastic.py
Original file line number Diff line number Diff line change
Expand Up @@ -728,8 +728,8 @@ def get_compliance_expansion(self):
if not self.order <= 4:
raise ValueError("Compliance tensor expansion only supported for fourth-order and lower")
ce_exp = [ElasticTensor(self[0]).compliance_tensor]
ein_string = "ijpq,pqrsuv,rskl,uvmn->ijklmn"
ce_exp.append(np.einsum(ein_string, -ce_exp[-1], self[1], ce_exp[-1], ce_exp[-1]))
ein_str = "ijpq,pqrsuv,rskl,uvmn->ijklmn"
ce_exp.append(np.einsum(ein_str, -ce_exp[-1], self[1], ce_exp[-1], ce_exp[-1]))
if self.order == 4:
# Four terms in the Fourth-Order compliance tensor
einstring_1 = "pqab,cdij,efkl,ghmn,abcdefgh"
Expand Down
15 changes: 7 additions & 8 deletions pymatgen/core/structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
from scipy.linalg import expm, polar
from scipy.spatial.distance import squareform
from tabulate import tabulate
from typing_extensions import Self

from pymatgen.core.bonds import CovalentBond, get_bond_length
from pymatgen.core.composition import Composition
Expand All @@ -60,6 +59,7 @@
from ase.optimize.optimize import Optimizer
from matgl.ext.ase import TrajectoryObserver
from numpy.typing import ArrayLike, NDArray
from typing_extensions import Self

from pymatgen.util.typing import CompositionLike, MillerIndex, PathLike, PbcLike, SpeciesLike

Expand Down Expand Up @@ -3363,14 +3363,12 @@ def break_bond(self, ind1: int, ind2: int, tol: float = 0.2) -> tuple[Self, Self
Args:
ind1 (int): 1st site index
ind2 (int): 2nd site index
tol (float): Relative tolerance to test. Basically, the code
checks if the distance between the sites is less than (1 +
tol) * typical bond distances. Defaults to 0.2, i.e.,
20% longer.
tol (float): Relative tolerance to test. Basically, the code checks if the distance
between the sites is less than (1 + tol) * typical bond distances.
Defaults to 0.2, i.e. 20% longer.
Returns:
Two IMolecule representing the clusters formed from
breaking the bond.
tuple[IMolecule, IMolecule]: The clusters formed from breaking the bond.
"""
clusters = ([self[ind1]], [self[ind2]])

Expand All @@ -3393,7 +3391,8 @@ def belongs_to_cluster(site, cluster):
raise ValueError("Not all sites are matched!")
sites = unmatched

return cast(tuple[Self, Self], tuple(map(type(self).from_sites, clusters)))
from_sites = type(self).from_sites
return from_sites(clusters[0]), from_sites(clusters[1])

def get_covalent_bonds(self, tol: float = 0.2) -> list[CovalentBond]:
"""Determine the covalent bonds in a molecule.
Expand Down
3 changes: 1 addition & 2 deletions pymatgen/io/abinit/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -1286,8 +1286,7 @@ def has_same_variable(kref, vref, other_inp):
return self[0].to_str(with_pseudos=with_pseudos)

def write(self, filepath="run.abi"):
"""
Write ndset input files to disk. The name of the file
"""Write ndset input files to disk. The name of the file
is constructed from the dataset index e.g. run0.abi.
"""
root, ext = os.path.splitext(filepath)
Expand Down
2 changes: 1 addition & 1 deletion pymatgen/io/abinit/netcdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def __init__(self, path):
self.ngroups = len(list(self.walk_tree()))

# Always return non-masked numpy arrays.
# Slicing a ncvar returns a MaskedArrray and this is really annoying
# Slicing a ncvar returns a MaskedArray and this is really annoying
# because it can lead to unexpected behavior in e.g. calls to np.matmul!
# See also https://github.com/Unidata/netcdf4-python/issues/785
self.rootgrp.set_auto_mask(False)
Expand Down
3 changes: 1 addition & 2 deletions pymatgen/io/adf.py
Original file line number Diff line number Diff line change
Expand Up @@ -533,8 +533,7 @@ def __init__(self, task):
self.task = task

def write_file(self, molecule, inp_file):
"""
Write an ADF input file.
"""Write an ADF input file.
Args:
molecule (Molecule): The molecule for this task.
Expand Down
6 changes: 2 additions & 4 deletions pymatgen/io/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,7 @@ def get_average_along_axis(self, ind):
return total / ng[(ind + 1) % 3] / ng[(ind + 2) % 3]

def to_hdf5(self, filename):
"""
Writes the VolumetricData to a HDF5 format, which is a highly optimized
"""Write the VolumetricData to a HDF5 format, which is a highly optimized
format for reading storing large data. The mapping of the VolumetricData
to this file format is as follows:
Expand Down Expand Up @@ -323,8 +322,7 @@ def from_hdf5(cls, filename: str, **kwargs) -> Self:
return cls(structure, data=data, data_aug=data_aug, **kwargs)

def to_cube(self, filename, comment: str = ""):
"""
Write the total volumetric data to a cube file format, which consists of two comment lines,
"""Write the total volumetric data to a cube file format, which consists of two comment lines,
a header section defining the structure IN BOHR, and the data.
Args:
Expand Down
6 changes: 2 additions & 4 deletions pymatgen/io/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ def get_str(self) -> str:
"""Return a string representation of an entire input file."""

def write_file(self, filename: str | PathLike) -> None:
"""
Write the input file.
"""Write the input file.
Args:
filename: The filename to output to, including path.
Expand Down Expand Up @@ -186,8 +185,7 @@ def write_input(
overwrite: bool = True,
zip_inputs: bool = False,
):
"""
Write Inputs to one or more files.
"""Write Inputs to one or more files.
Args:
directory: Directory to write input files to
Expand Down
3 changes: 1 addition & 2 deletions pymatgen/io/cssr.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,7 @@ def __str__(self):
return "\n".join(output)

def write_file(self, filename):
"""
Write out a CSSR file.
"""Write out a CSSR file.
Args:
filename (str): Filename to write to.
Expand Down
9 changes: 3 additions & 6 deletions pymatgen/io/exciting/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,7 @@ def from_file(cls, filename: str | Path) -> Self:
return cls.from_str(data)

def write_etree(self, celltype, cartesian=False, bandstr=False, symprec: float = 0.4, angle_tolerance=5, **kwargs):
"""
Writes the exciting input parameters to an xml object.
"""Write the exciting input parameters to an XML object.
Args:
celltype (str): Choice of unit cell. Can be either the unit cell
Expand Down Expand Up @@ -278,8 +277,7 @@ def write_etree(self, celltype, cartesian=False, bandstr=False, symprec: float =
return root

def write_string(self, celltype, cartesian=False, bandstr=False, symprec: float = 0.4, angle_tolerance=5, **kwargs):
"""
Writes exciting input.xml as a string.
"""Write exciting input.xml as a string.
Args:
celltype (str): Choice of unit cell. Can be either the unit cell
Expand Down Expand Up @@ -315,8 +313,7 @@ def write_string(self, celltype, cartesian=False, bandstr=False, symprec: float
def write_file(
self, celltype, filename, cartesian=False, bandstr=False, symprec: float = 0.4, angle_tolerance=5, **kwargs
):
"""
Writes exciting input file.
"""Write exciting input file.
Args:
celltype (str): Choice of unit cell. Can be either the unit cell
Expand Down
17 changes: 5 additions & 12 deletions pymatgen/io/feff/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,8 +360,7 @@ def __str__(self):
return "\n".join(output)

def write_file(self, filename="HEADER"):
"""
Writes Header into filename on disk.
"""Write Header to file.
Args:
filename: Filename and path for file to be written to disk
Expand Down Expand Up @@ -507,8 +506,7 @@ def __str__(self):
return f"ATOMS\n{atom_list}\nEND\n"

def write_file(self, filename="ATOMS"):
"""
Write Atoms list to file.
"""Write Atoms list to file.
Args:
filename: path for file to be written
Expand Down Expand Up @@ -627,8 +625,7 @@ def __str__(self):
return self.get_str()

def write_file(self, filename="PARAMETERS"):
"""
Write Tags to a Feff parameter tag file.
"""Write Tags to a Feff parameter tag file.
Args:
filename: filename and path to write to.
Expand Down Expand Up @@ -908,8 +905,7 @@ def __str__(self):
return f"POTENTIALS \n{ipotlist}"

def write_file(self, filename="POTENTIALS"):
"""
Write to file.
"""Write to file.
Args:
filename: filename and path to write potential file to.
Expand Down Expand Up @@ -982,10 +978,7 @@ def get_atom_map(structure, absorbing_atom=None):
if absorbing_atom and len(structure.indices_from_symbol(absorbing_atom)) == 1:
unique_pot_atoms.remove(absorbing_atom)

atom_map = {}
for idx, atom in enumerate(unique_pot_atoms, start=1):
atom_map[atom] = idx
return atom_map
return {atom: idx for idx, atom in enumerate(unique_pot_atoms, start=1)}


def get_absorbing_atom_symbol_index(absorbing_atom, structure):
Expand Down
3 changes: 1 addition & 2 deletions pymatgen/io/feff/sets.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,7 @@ def all_input(self):
return dct

def write_input(self, output_dir=".", make_dir_if_not_present=True):
"""
Writes a set of FEFF input to a directory.
"""Write a FEFF input set to a directory.
Args:
output_dir: Directory to output the FEFF input files
Expand Down
3 changes: 1 addition & 2 deletions pymatgen/io/fiesta.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,8 +528,7 @@ def __str__(self):
)

def write_file(self, filename: str | Path) -> None:
"""
Write FiestaInput to a file
"""Write FiestaInput to a file
Args:
filename: Filename.
Expand Down
Loading

0 comments on commit eccf075

Please sign in to comment.