diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index a727f6d7910..4c63a00a60c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -2,3 +2,5 @@ pymatgen/io/ase.py @Andrew-S-Rosen pymatgen/io/abinit/* @gmatteo pymatgen/io/lobster/* @JaGeo +pymatgen/ext/* @ml-evs +tests/ext/* @ml-evs diff --git a/.github/release.yml b/.github/release.yml index 5bc3ec2d50c..1eb9bf3b135 100644 --- a/.github/release.yml +++ b/.github/release.yml @@ -14,6 +14,8 @@ changelog: labels: [housekeeping] - title: ๐ Performance labels: [performance] + - title: ๐ง CI + labels: [ci] - title: ๐ก Refactoring labels: [refactor] - title: ๐งช Tests diff --git a/.github/workflows/issue-metrics.yml b/.github/workflows/issue-metrics.yml new file mode 100644 index 00000000000..26e498a56ae --- /dev/null +++ b/.github/workflows/issue-metrics.yml @@ -0,0 +1,42 @@ +name: Monthly issue metrics +on: + workflow_dispatch: + schedule: + - cron: '3 2 1 * *' + +permissions: + contents: read + +jobs: + build: + name: issue metrics + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: read + steps: + - name: Get dates for last month + shell: bash + run: | + # Calculate the first day of the previous month + first_day=$(date -d "last month" +%Y-%m-01) + + # Calculate the last day of the previous month + last_day=$(date -d "$first_day +1 month -1 day" +%Y-%m-%d) + + #Set an environment variable with the date range + echo "$first_day..$last_day" + echo "last_month=$first_day..$last_day" >> "$GITHUB_ENV" + + - name: Run issue-metrics tool + uses: github/issue-metrics@v3 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SEARCH_QUERY: 'repo:materialsproject/pymatgen is:issue created:${{ env.last_month }} -reason:"not planned"' + + - name: Create issue + uses: peter-evans/create-issue-from-file@v5 + with: + title: Monthly issue metrics report + token: ${{ secrets.GITHUB_TOKEN }} + content-filepath: ./issue_metrics.md diff --git a/.github/workflows/jekyll-gh-pages.yml b/.github/workflows/jekyll-gh-pages.yml index 308873fc823..91f17b3ea39 100644 --- a/.github/workflows/jekyll-gh-pages.yml +++ b/.github/workflows/jekyll-gh-pages.yml @@ -1,15 +1,11 @@ -# Sample workflow for building and deploying a Jekyll site to GitHub Pages name: Deploy Jekyll with GitHub Pages dependencies preinstalled on: - # Runs on pushes targeting the default branch push: branches: ["master"] + workflow_dispatch: # enable manual workflow execution - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +# Set permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages permissions: contents: read pages: write @@ -22,23 +18,26 @@ concurrency: cancel-in-progress: false jobs: - # Build job build: + # prevent this action from running on forks + if: github.repository == 'materialsproject/pymatgen' runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 + - name: Setup Pages uses: actions/configure-pages@v3 + - name: Build with Jekyll uses: actions/jekyll-build-pages@v1 with: source: ./docs destination: ./_site + - name: Upload artifact uses: actions/upload-pages-artifact@v2 - # Deployment job deploy: environment: name: github-pages diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index dbdf64a779c..cacd81dcf36 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -27,7 +27,7 @@ jobs: - name: ruff run: | ruff --version - ruff . + ruff check . ruff format --check . - name: mypy diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ad6a6eecea0..24b61d90aac 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,6 +19,9 @@ jobs: test: # prevent this action from running on forks if: github.repository == 'materialsproject/pymatgen' + defaults: + run: + shell: bash -l {0} # enables conda/mamba env activation by reading bash profile strategy: fail-fast: false matrix: @@ -48,65 +51,41 @@ jobs: - name: Check out repo uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - cache: pip - cache-dependency-path: setup.py + - name: Set up micromamba + uses: mamba-org/setup-micromamba@main + + - name: Create mamba environment + run: | + micromamba create -n pmg python=${{ matrix.python-version }} --yes - name: Install uv - run: pip install uv + run: micromamba run -n pmg pip install uv - name: Copy GULP to bin if: matrix.os == 'ubuntu-latest' run: | sudo cp cmd_line/gulp/Linux_64bit/* /usr/local/bin/ - - name: Install Bader + - name: Install ubuntu-only conda dependencies if: matrix.os == 'ubuntu-latest' run: | - wget https://theory.cm.utexas.edu/henkelman/code/bader/download/bader_lnx_64.tar.gz - tar xvzf bader_lnx_64.tar.gz - sudo mv bader /usr/local/bin/ - continue-on-error: true # This is not critical to succeed. + micromamba install -n pmg -c conda-forge enumlib packmol bader openbabel openff-toolkit --yes - - name: Install Enumlib - if: matrix.os == 'ubuntu-latest' + - name: Install pymatgen and dependencies run: | - git clone --recursive https://github.com/msg-byu/enumlib.git - cd enumlib/symlib/src - export F90=gfortran - make - cd ../../src - make enum.x - sudo mv enum.x /usr/local/bin/ - cd .. - sudo cp aux_src/makeStr.py /usr/local/bin/ - continue-on-error: true # This is not critical to succeed. - - - name: Install Packmol - if: matrix.os == 'ubuntu-latest' - run: | - wget -O packmol.tar.gz https://github.com/m3g/packmol/archive/refs/tags/v20.14.2.tar.gz - tar xvzf packmol.tar.gz - export F90=gfortran - cd packmol-20.14.2 - ./configure - make - sudo mv packmol /usr/local/bin/ - cd .. - continue-on-error: true # This is not critical to succeed. - - - name: Install dependencies - run: | - uv pip install numpy cython --system + micromamba activate pmg + # TODO remove temporary fix. added since uv install torch is flaky. + # track https://github.com/astral-sh/uv/issues/1921 for resolution + pip install torch + + uv pip install numpy cython - uv pip install -e '.[dev,optional]' --system + uv pip install --editable '.[dev,optional]' # TODO remove next line installing ase from main branch when FrechetCellFilter is released - uv pip install --upgrade 'ase@git+https://gitlab.com/ase/ase' --system + uv pip install --upgrade 'git+https://gitlab.com/ase/ase' - name: pytest split ${{ matrix.split }} run: | + micromamba activate pmg pytest --splits 10 --group ${{ matrix.split }} --durations-path tests/files/.pytest-split-durations tests diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 81032d2aeda..a6745467041 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,14 +8,14 @@ ci: repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.3.3 + rev: v0.3.7 hooks: - id: ruff args: [--fix, --unsafe-fixes] - id: ruff-format - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v4.6.0 hooks: - id: check-yaml - id: end-of-file-fixer diff --git a/dev_scripts/chemenv/equivalent_indices.py b/dev_scripts/chemenv/equivalent_indices.py index 4e1250b58e8..1d30564b05f 100644 --- a/dev_scripts/chemenv/equivalent_indices.py +++ b/dev_scripts/chemenv/equivalent_indices.py @@ -99,9 +99,9 @@ # 0. any point for i0 in range(8): # 1. point opposite to point 0. in the square face - if i0 in [0, 2]: + if i0 in {0, 2}: i1 = i0 + 1 - elif i0 in [1, 3]: + elif i0 in {1, 3}: i1 = i0 - 1 elif i0 == 4: i1 = 7 @@ -111,10 +111,14 @@ i1 = 5 elif i0 == 7: i1 = 4 + else: + raise RuntimeError("Cannot determine point.") + # 2. one of the two last points in the square face sfleft = list(sf1) if i0 in sf1 else list(sf2) sfleft.remove(i0) sfleft.remove(i1) + i2 = 0 for i2 in sfleft: sfleft2 = list(sfleft) sfleft2.remove(i2) diff --git a/dev_scripts/chemenv/get_plane_permutations_optimized.py b/dev_scripts/chemenv/get_plane_permutations_optimized.py index d0d86273957..47ed4f13b93 100644 --- a/dev_scripts/chemenv/get_plane_permutations_optimized.py +++ b/dev_scripts/chemenv/get_plane_permutations_optimized.py @@ -279,7 +279,7 @@ def random_permutations_iterator(initial_permutation, n_permutations): f"Get the explicit optimized permutations for geometry {cg.name!r} (symbol : " f'{cg_symbol!r}) ? ("y" to confirm, "q" to quit)\n' ) - if test not in ["y", "q"]: + if test not in ("y", "q"): print("Wrong key, try again") continue if test == "y": diff --git a/dev_scripts/chemenv/strategies/multi_weights_strategy_parameters.py b/dev_scripts/chemenv/strategies/multi_weights_strategy_parameters.py index 7b1f40218bd..06e5841d155 100644 --- a/dev_scripts/chemenv/strategies/multi_weights_strategy_parameters.py +++ b/dev_scripts/chemenv/strategies/multi_weights_strategy_parameters.py @@ -151,17 +151,18 @@ def get_structure(self, morphing_factor): coords = copy.deepcopy(self.abstract_geometry.points_wcs_ctwcc()) bare_points = self.abstract_geometry.bare_points_with_centre + origin = None for morphing in self.morphing_description: - if morphing["site_type"] == "neighbor": - i_site = morphing["ineighbor"] + 1 - if morphing["expansion_origin"] == "central_site": - origin = bare_points[0] - vector = bare_points[i_site] - origin - coords[i_site] += vector * (morphing_factor - 1.0) - else: + if morphing["site_type"] != "neighbor": raise ValueError(f"Key \"site_type\" is {morphing['site_type']} while it can only be neighbor") + i_site = morphing["ineighbor"] + 1 + if morphing["expansion_origin"] == "central_site": + origin = bare_points[0] + vector = bare_points[i_site] - origin + coords[i_site] += vector * (morphing_factor - 1.0) + return Structure(lattice=lattice, species=species, coords=coords, coords_are_cartesian=True) def estimate_parameters(self, dist_factor_min, dist_factor_max, symmetry_measure_type="csm_wcs_ctwcc"): @@ -269,7 +270,7 @@ def get_weights(self, weights_options): "+-------------------------------------------------------------+\n" ) - with open("ce_pairs.json") as file: + with open("ce_pairs.json", encoding="utf-8") as file: ce_pairs = json.load(file) self_weight_max_csms: dict[str, list[float]] = {} self_weight_max_csms_per_cn: dict[str, list[float]] = {} diff --git a/dev_scripts/chemenv/view_environment.py b/dev_scripts/chemenv/view_environment.py index 17a1df52428..2caa22e9f34 100644 --- a/dev_scripts/chemenv/view_environment.py +++ b/dev_scripts/chemenv/view_environment.py @@ -52,6 +52,7 @@ print() # Visualize the separation plane of a given algorithm sep_plane = False + algo = None if any(algo.algorithm_type == SEPARATION_PLANE for algo in cg.algorithms): test = input("Enter index of the algorithm for which you want to visualize the plane : ") if test != "": diff --git a/dev_scripts/potcar_scrambler.py b/dev_scripts/potcar_scrambler.py index fe6d659cf94..639c366bc7c 100644 --- a/dev_scripts/potcar_scrambler.py +++ b/dev_scripts/potcar_scrambler.py @@ -4,6 +4,7 @@ import shutil import warnings from glob import glob +from typing import TYPE_CHECKING import numpy as np from monty.os.path import zpath @@ -14,6 +15,9 @@ from pymatgen.io.vasp.sets import _load_yaml_config from pymatgen.util.testing import VASP_IN_DIR +if TYPE_CHECKING: + from typing_extensions import Self + class PotcarScrambler: """ @@ -34,18 +38,14 @@ class PotcarScrambler: from existing POTCAR `input_filename` """ - def __init__(self, potcars: Potcar | PotcarSingle): - if isinstance(potcars, PotcarSingle): - self.PSP_list = [potcars] - else: - self.PSP_list = potcars + def __init__(self, potcars: Potcar | PotcarSingle) -> None: + self.PSP_list = [potcars] if isinstance(potcars, PotcarSingle) else potcars self.scrambled_potcars_str = "" for psp in self.PSP_list: scrambled_potcar_str = self.scramble_single_potcar(psp) self.scrambled_potcars_str += scrambled_potcar_str - return - def _rand_float_from_str_with_prec(self, input_str: str, bloat: float = 1.5): + def _rand_float_from_str_with_prec(self, input_str: str, bloat: float = 1.5) -> float: n_prec = len(input_str.split(".")[1]) bd = max(1, bloat * abs(float(input_str))) return round(bd * np.random.rand(1)[0], n_prec) @@ -53,7 +53,7 @@ def _rand_float_from_str_with_prec(self, input_str: str, bloat: float = 1.5): def _read_fortran_str_and_scramble(self, input_str: str, bloat: float = 1.5): input_str = input_str.strip() - if input_str.lower() in ("t", "f", "true", "false"): + if input_str.lower() in {"t", "f", "true", "false"}: return bool(np.random.randint(2)) if input_str.upper() == input_str.lower() and input_str[0].isnumeric(): @@ -68,7 +68,7 @@ def _read_fortran_str_and_scramble(self, input_str: str, bloat: float = 1.5): except ValueError: return input_str - def scramble_single_potcar(self, potcar: PotcarSingle): + def scramble_single_potcar(self, potcar: PotcarSingle) -> str: """ Scramble the body of a POTCAR, retain the PSCTR header information. @@ -124,12 +124,12 @@ def scramble_single_potcar(self, potcar: PotcarSingle): ) return scrambled_potcar_str - def to_file(self, filename: str): + def to_file(self, filename: str) -> None: with zopen(filename, mode="wt") as file: file.write(self.scrambled_potcars_str) @classmethod - def from_file(cls, input_filename: str, output_filename: str | None = None): + def from_file(cls, input_filename: str, output_filename: str | None = None) -> Self: psp = Potcar.from_file(input_filename) psp_scrambled = cls(psp) if output_filename: @@ -137,7 +137,7 @@ def from_file(cls, input_filename: str, output_filename: str | None = None): return psp_scrambled -def generate_fake_potcar_libraries(): +def generate_fake_potcar_libraries() -> None: """ To test the `_gen_potcar_summary_stats` function in `pymatgen.io.vasp.inputs`, need a library of fake POTCARs which do not violate copyright @@ -173,7 +173,7 @@ def generate_fake_potcar_libraries(): break -def potcar_cleanser(): +def potcar_cleanser() -> None: """ Function to replace copyrighted POTCARs used in io.vasp.sets testing with dummy POTCARs that have scrambled PSP and kinetic energy values diff --git a/dev_scripts/regen_libxcfunc.py b/dev_scripts/regen_libxcfunc.py index 2965acab22e..1c0491d112c 100755 --- a/dev_scripts/regen_libxcfunc.py +++ b/dev_scripts/regen_libxcfunc.py @@ -50,16 +50,16 @@ def write_libxc_docs_json(xc_funcs, json_path): xc_funcs = deepcopy(xc_funcs) # Remove XC_FAMILY from Family and XC_ from Kind to make strings more human-readable. - for d in xc_funcs.values(): - d["Family"] = d["Family"].replace("XC_FAMILY_", "", 1) - d["Kind"] = d["Kind"].replace("XC_", "", 1) + for dct in xc_funcs.values(): + dct["Family"] = dct["Family"].replace("XC_FAMILY_", "", 1) + dct["Kind"] = dct["Kind"].replace("XC_", "", 1) # Build lightweight version with a subset of keys. - for num, d in xc_funcs.items(): - xc_funcs[num] = {key: d[key] for key in ("Family", "Kind", "References")} + for num, dct in xc_funcs.items(): + xc_funcs[num] = {key: dct[key] for key in ("Family", "Kind", "References")} # Descriptions are optional for opt in ("Description 1", "Description 2"): - desc = d.get(opt) + desc = dct.get(opt) if desc is not None: xc_funcs[num][opt] = desc diff --git a/dev_scripts/update_pt_data.py b/dev_scripts/update_pt_data.py index 3c740e2255a..178c2ce394b 100644 --- a/dev_scripts/update_pt_data.py +++ b/dev_scripts/update_pt_data.py @@ -128,16 +128,16 @@ def parse_radii(): def update_ionic_radii(): data = loadfn(ptable_yaml_path) - for d in data.values(): - if "Ionic_radii" in d: - d["Ionic radii"] = {k: v / 100 for k, v in d["Ionic_radii"].items()} - del d["Ionic_radii"] - if "Ionic_radii_hs" in d: - d["Ionic radii hs"] = {k: v / 100 for k, v in d["Ionic_radii_hs"].items()} - del d["Ionic_radii_hs"] - if "Ionic_radii_ls" in d: - d["Ionic radii ls"] = {k: v / 100 for k, v in d["Ionic_radii_ls"].items()} - del d["Ionic_radii_ls"] + for dct in data.values(): + if "Ionic_radii" in dct: + dct["Ionic radii"] = {k: v / 100 for k, v in dct["Ionic_radii"].items()} + del dct["Ionic_radii"] + if "Ionic_radii_hs" in dct: + dct["Ionic radii hs"] = {k: v / 100 for k, v in dct["Ionic_radii_hs"].items()} + del dct["Ionic_radii_hs"] + if "Ionic_radii_ls" in dct: + dct["Ionic radii ls"] = {k: v / 100 for k, v in dct["Ionic_radii_ls"].items()} + del dct["Ionic_radii_ls"] with open("periodic_table2.yaml", mode="w") as file: yaml.dump(data, file) with open("../pymatgen/core/periodic_table.json", mode="w") as file: @@ -150,9 +150,10 @@ def parse_shannon_radii(): from openpyxl import load_workbook wb = load_workbook("Shannon Radii.xlsx") - print(wb.get_sheet_names()) + print(wb.sheetnames()) sheet = wb["Sheet1"] i = 2 + el = charge = cn = None radii = collections.defaultdict(dict) while sheet[f"E{i}"].value: if sheet[f"A{i}"].value: @@ -162,8 +163,7 @@ def parse_shannon_radii(): radii[el][charge] = {} if sheet[f"C{i}"].value: cn = sheet[f"C{i}"].value - if cn not in radii[el][charge]: - radii[el][charge][cn] = {} + radii[el][charge].setdefault(cn, {}) spin = sheet[f"D{i}"].value if sheet[f"D{i}"].value is not None else "" @@ -236,6 +236,7 @@ def add_electron_affinities(): req = requests.get("https://wikipedia.org/wiki/Electron_affinity_(data_page)") soup = BeautifulSoup(req.text, "html.parser") + table = None for table in soup.find_all("table"): if "Hydrogen" in table.text: break @@ -272,6 +273,7 @@ def add_ionization_energies(): with open("NIST Atomic Ionization Energies Output.html") as file: soup = BeautifulSoup(file.read(), "html.parser") + table = None for table in soup.find_all("table"): if "Hydrogen" in table.text: break diff --git a/docs/CHANGES.md b/docs/CHANGES.md index 6ec54785c29..cd1d4cebf39 100644 --- a/docs/CHANGES.md +++ b/docs/CHANGES.md @@ -6,6 +6,107 @@ nav_order: 4 # Changelog +## v2024.4.13 + +Hot fix release for [v2024.4.12](#v2024412) to be yanked on PyPI due to https://github.com/materialsproject/pymatgen/issues/3751. + +### ๐ Bug Fixes + +* Revert mistaken `Cohp.has_antibnd_states_below_efermi` rename by @JaGeo in https://github.com/materialsproject/pymatgen/pull/3750 +* Fix `typing_extension` `ImportError` in downstream packages by @janosh in https://github.com/materialsproject/pymatgen/pull/3752 +* Update some of the OPTIMADE aliases by @ml-evs in https://github.com/materialsproject/pymatgen/pull/3754 + +### ๐งน House-Keeping + +* Remove duplicate ruff rule in `pyproject.toml` by @Andrew-S-Rosen in https://github.com/materialsproject/pymatgen/pull/3755 + +**Full Changelog**: https://github.com/materialsproject/pymatgen/compare/v2024.4.12...v2024.4.13 + +## v2024.4.12 + +### ๐ New Features + +* Add `pymatgen.io.openff` module by @orionarcher in https://github.com/materialsproject/pymatgen/pull/3729 + +### ๐ Bug Fixes + +* Fix blank line bug in `io.res.ResWriter` by @stefsmeets in https://github.com/materialsproject/pymatgen/pull/3671 +* Reset label for sites changed by `Structure.replace_species()` by @stefsmeets in https://github.com/materialsproject/pymatgen/pull/3672 +* Fix `phonopy.get_pmg_structure` `site_properties` key for magmoms by @JonathanSchmidt1 in https://github.com/materialsproject/pymatgen/pull/3679 +* Improve Bandoverlaps parser by @naik-aakash in https://github.com/materialsproject/pymatgen/pull/3689 +* Convert some `staticmethod` to `classmethod` by @DanielYang59 in https://github.com/materialsproject/pymatgen/pull/3710 +* Correct units of Element.atomic_orbitals by @esoteric-ephemera in https://github.com/materialsproject/pymatgen/pull/3714 +* Add a fix for if a parameter is None in AimsControlIn by @tpurcell90 in https://github.com/materialsproject/pymatgen/pull/3727 +* Replace general `raise Exception` and add missing `raise` keyword by @DanielYang59 in https://github.com/materialsproject/pymatgen/pull/3728 +* Fix `ChemicalPotentialDiagram` 2D plot not respecting `formal_chempots` setting by @uliaschauer in https://github.com/materialsproject/pymatgen/pull/3734 +* Update ENCUT type to float in incar_parameters.json by @yuuukuma in https://github.com/materialsproject/pymatgen/pull/3741 +* Clean up `core.surface` comments and docstrings by @DanielYang59 in https://github.com/materialsproject/pymatgen/pull/3691 +* Fix `io.cp2k.input.DataFile` by @DanielYang59 in https://github.com/materialsproject/pymatgen/pull/3745 + +### ๐ Enhancements + +* Ensure `MSONAtoms` is indeed `MSONable` when `Atoms.info` is loaded with goodies by @Andrew-S-Rosen in https://github.com/materialsproject/pymatgen/pull/3670 +* Generalize fatband plots from Lobster by @JaGeo in https://github.com/materialsproject/pymatgen/pull/3688 +* Plotting of Multicenter COBIs by @JaGeo in https://github.com/materialsproject/pymatgen/pull/2926 +* Support appending vectors to positions in XSF format by @mturiansky in https://github.com/materialsproject/pymatgen/pull/3704 +* Define `needs_u_correction(comp: CompositionLike) -> set[str]` utility function by @janosh in https://github.com/materialsproject/pymatgen/pull/3703 +* Add more flexibility to `PhononDOSPlotter` and `PhononBSPlotter` by @ab5424 in https://github.com/materialsproject/pymatgen/pull/3700 +* Define `ElementType` enum in `core/periodic_table.py` by @janosh in https://github.com/materialsproject/pymatgen/pull/3726 + +### ๐ง CI + +* Migrate CI dependency installation from `pip` to `uv` by @janosh in https://github.com/materialsproject/pymatgen/pull/3675 +* Prevent GitHub Actions from running docs-related CI on forks by @lan496 in https://github.com/materialsproject/pymatgen/pull/3697 + +### ๐ Documentation + +* Reformat docstrings to Google style and add type annotations by @DanielYang59 in https://github.com/materialsproject/pymatgen/pull/3694 +* Breaking: all plot methods return `plt.Axes` by @janosh in https://github.com/materialsproject/pymatgen/pull/3749 + +### ๐งน House-Keeping + +* Clean up test files: VASP outputs by @DanielYang59 in https://github.com/materialsproject/pymatgen/pull/3653 +* Clean up test files: VASP inputs by @DanielYang59 in https://github.com/materialsproject/pymatgen/pull/3674 +* Clean up test files: dedicated VASP directories, `xyz`, `mcif`, `cssr`, `exciting`, `wannier90` by @DanielYang59 in https://github.com/materialsproject/pymatgen/pull/3681 +* Remove exception printing when importing phonopy by @lan496 in https://github.com/materialsproject/pymatgen/pull/3696 +* Standardize test names: e.g. `LatticeTestCase` -> `TestLattice` by @janosh in https://github.com/materialsproject/pymatgen/pull/3693 +* Clean up tests by @janosh in https://github.com/materialsproject/pymatgen/pull/3713 +* Fix import order for `if TYPE_CHECKING:` block by @DanielYang59 in https://github.com/materialsproject/pymatgen/pull/3711 +* Use `Self` type in Method Signatures by @DanielYang59 in https://github.com/materialsproject/pymatgen/pull/3705 +* Remove deprecated `analysis.interface`, rename classes to PascalCase and rename `with_*` to `from_*` by @DanielYang59 in https://github.com/materialsproject/pymatgen/pull/3725 +* Test `EntrySet.ground_states` and CIF writing in `NEBSet.write_input` by @janosh in https://github.com/materialsproject/pymatgen/pull/3732 + +### ๐ Performance + +* Dynamic `__hash__` for `BalancedReaction` by @DanielYang59 in https://github.com/materialsproject/pymatgen/pull/3676 + +### ๐งช Tests + +* Clean up tests 2 by @janosh in https://github.com/materialsproject/pymatgen/pull/3716 +* Remove unnecessary `unittest.TestCase` subclassing by @janosh in https://github.com/materialsproject/pymatgen/pull/3718 + +### ๐ Security Fixes + +* Avoid using `exec` in code by @DanielYang59 in https://github.com/materialsproject/pymatgen/pull/3736 +* Avoid using `eval`, replace manual offset in `enumerate` and rename single letter variables by @DanielYang59 in https://github.com/materialsproject/pymatgen/pull/3739 + +### ๐ท๏ธ Type Hints + +* `Self` return type on `from_dict` methods by @janosh in https://github.com/materialsproject/pymatgen/pull/3702 +* Return `self` from `Structure` methods `replace`, `substitute`, `remove_species`, `remove_sites` by @janosh in https://github.com/materialsproject/pymatgen/pull/3706 +* `Self` return type on `Lattice` methods by @janosh in https://github.com/materialsproject/pymatgen/pull/3707 + +### ๐คทโโ๏ธ Other Changes + +* `os.path.(exists->isfile)` by @janosh in https://github.com/materialsproject/pymatgen/pull/3690 + +## New Contributors + +* @JonathanSchmidt1 made their first contribution in https://github.com/materialsproject/pymatgen/pull/3679 +* @uliaschauer made their first contribution in https://github.com/materialsproject/pymatgen/pull/3734 + +**Full Changelog**: https://github.com/materialsproject/pymatgen/compare/v2024.3.1...v2024.4.12 + ## v2024.3.1 ## What's Changed diff --git a/docs/apidoc/pymatgen.io.aims.rst b/docs/apidoc/pymatgen.io.aims.rst index 800001df3c5..7949c7d0e56 100644 --- a/docs/apidoc/pymatgen.io.aims.rst +++ b/docs/apidoc/pymatgen.io.aims.rst @@ -6,6 +6,14 @@ pymatgen.io.aims package :undoc-members: :show-inheritance: +Subpackages +----------- + +.. toctree:: + :maxdepth: 7 + + pymatgen.io.aims.sets + Submodules ---------- diff --git a/docs/apidoc/pymatgen.io.aims.sets.rst b/docs/apidoc/pymatgen.io.aims.sets.rst new file mode 100644 index 00000000000..29a1aafbd4f --- /dev/null +++ b/docs/apidoc/pymatgen.io.aims.sets.rst @@ -0,0 +1,34 @@ +pymatgen.io.aims.sets package +============================= + +.. automodule:: pymatgen.io.aims.sets + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +pymatgen.io.aims.sets.base module +--------------------------------- + +.. automodule:: pymatgen.io.aims.sets.base + :members: + :undoc-members: + :show-inheritance: + +pymatgen.io.aims.sets.bs module +------------------------------- + +.. automodule:: pymatgen.io.aims.sets.bs + :members: + :undoc-members: + :show-inheritance: + +pymatgen.io.aims.sets.core module +--------------------------------- + +.. automodule:: pymatgen.io.aims.sets.core + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/apidoc/pymatgen.io.rst b/docs/apidoc/pymatgen.io.rst index ed205163887..3d276f7d2fe 100644 --- a/docs/apidoc/pymatgen.io.rst +++ b/docs/apidoc/pymatgen.io.rst @@ -104,6 +104,14 @@ pymatgen.io.gaussian module :undoc-members: :show-inheritance: +pymatgen.io.icet module +----------------------- + +.. automodule:: pymatgen.io.icet + :members: + :undoc-members: + :show-inheritance: + pymatgen.io.jarvis module ------------------------- diff --git a/docs/apidoc/pymatgen.util.rst b/docs/apidoc/pymatgen.util.rst index 807645b00d9..8a645ccb065 100644 --- a/docs/apidoc/pymatgen.util.rst +++ b/docs/apidoc/pymatgen.util.rst @@ -6,6 +6,14 @@ pymatgen.util package :undoc-members: :show-inheritance: +Subpackages +----------- + +.. toctree:: + :maxdepth: 7 + + pymatgen.util.testing + Submodules ---------- @@ -89,14 +97,6 @@ pymatgen.util.string module :undoc-members: :show-inheritance: -pymatgen.util.testing module ----------------------------- - -.. automodule:: pymatgen.util.testing - :members: - :undoc-members: - :show-inheritance: - pymatgen.util.typing module --------------------------- diff --git a/docs/apidoc/pymatgen.util.testing.rst b/docs/apidoc/pymatgen.util.testing.rst new file mode 100644 index 00000000000..0ee4fd38001 --- /dev/null +++ b/docs/apidoc/pymatgen.util.testing.rst @@ -0,0 +1,18 @@ +pymatgen.util.testing package +============================= + +.. automodule:: pymatgen.util.testing + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +pymatgen.util.testing.aims module +--------------------------------- + +.. automodule:: pymatgen.util.testing.aims + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/modules.html b/docs/modules.html index 97adb20638f..d6d5696b2a3 100644 --- a/docs/modules.html +++ b/docs/modules.html @@ -4,7 +4,7 @@ -