From 6ee884015a266875308addcc8d0b45d642ba41d7 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Thu, 16 Oct 2025 11:45:36 +0200 Subject: [PATCH 1/4] remove pdm dev-dependency section in pyproject (likely not needed?) https://github.com/materialsproject/pymatgen/commit/fb6ba71dac3cf6a079aaa2b85c0e4971434ba1ad --- pyproject.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index fb44cbce142..509b2630166 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -164,10 +164,6 @@ include = ["pymatgen", "pymatgen.*"] "pymatgen.io.lammps" = ["CoeffsDataType.yaml", "templates/*.template"] "pymatgen.symmetry" = ["*.json", "*.sqlite", "*.yaml"] -[tool.pdm.dev-dependencies] -lint = ["mypy>=1.10.0", "pre-commit>=3.7.1", "ruff>=0.4.9"] -test = ["pytest-cov>=5.0.0", "pytest-split>=0.9.0", "pytest>=8.2.2","pytest-xdist>=3.0.0"] - [tool.cibuildwheel.linux] archs = ["auto64"] skip = ["*musllinux*"] From c574301b10143dc27b7aad37c016d627780ed763 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Thu, 9 Oct 2025 21:40:23 +0200 Subject: [PATCH 2/4] clean up tool.coverage exclude section remove self explanatory comment --- pyproject.toml | 7 +------ src/pymatgen/io/vasp/outputs.py | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 509b2630166..769472cd552 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -257,7 +257,7 @@ docstring-code-format = true addopts = "-n auto --durations=30 --quiet -r xXs --color=yes --import-mode=importlib" filterwarnings = [ # NOTE: the LAST matching option would be used - "ignore::UserWarning", # Ignore UserWarning + "ignore::UserWarning", ] [tool.coverage.run] @@ -273,12 +273,7 @@ omit = [ [tool.coverage.report] exclude_also = [ "@deprecated", - "def __repr__", "except ImportError:", - "if TYPE_CHECKING:", - "if self.debug:", - "if settings.DEBUG", - "pragma: no cover", "raise NotImplementedError", "show_plot", ] diff --git a/src/pymatgen/io/vasp/outputs.py b/src/pymatgen/io/vasp/outputs.py index fbba3d7a4fb..e2629efa389 100644 --- a/src/pymatgen/io/vasp/outputs.py +++ b/src/pymatgen/io/vasp/outputs.py @@ -5828,7 +5828,7 @@ def read_data(dtype): @property def cder(self) -> NDArray: """The complex derivative of the orbitals with respect to k.""" - if self.cder_real.shape[0] != self.cder_real.shape[1]: # pragma: no cover + if self.cder_real.shape[0] != self.cder_real.shape[1]: warnings.warn( "Not all band pairs are present in the WAVEDER file." "If you want to get all the matrix elements set LVEL=.True. in the INCAR.", From f2424fddd92f3fee722adb057f16918c0d758dc7 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Tue, 14 Oct 2025 08:45:50 +0200 Subject: [PATCH 3/4] skip netcdf4 test in Linux CI >=1.6.5, clean up tests xfail for netcdf4 in ubuntu CI --- tests/io/abinit/test_netcdf.py | 39 +++++++++++++++------------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/tests/io/abinit/test_netcdf.py b/tests/io/abinit/test_netcdf.py index 59331aaf3a8..8513c1e71f9 100644 --- a/tests/io/abinit/test_netcdf.py +++ b/tests/io/abinit/test_netcdf.py @@ -1,6 +1,7 @@ from __future__ import annotations import os +import sys import tarfile import numpy as np @@ -60,7 +61,6 @@ def test_read_si2(self): for varname, float_ref in ref_float_values.items(): value = data.read_value(varname) assert_allclose(value, float_ref) - # assert 0 # Reading non-existent variables or dims should raise # a subclass of NetcdReaderError @@ -83,36 +83,31 @@ def test_read_si2(self): # xc = data.read_abinit_xcfunc() # assert xc == "LDA" - @pytest.mark.skipif(netCDF4 is None or True, reason="Requires Netcdf4") - def test_read_fe(self): - with tarfile.open(f"{TEST_DIR}/Fe_magmoms_collinear_GSR.tar.xz", mode="r:xz") as t: + @pytest.mark.skipif(netCDF4 is None, reason="Requires NetCDF4") + @pytest.mark.xfail( + sys.platform.startswith("linux") and os.getenv("CI") and netCDF4.__version__ >= "1.6.5", + reason="Fails with netCDF4 >= 1.6.5 on Ubuntu CI", + ) + @pytest.mark.parametrize( + ("tarname", "expected"), + [ + ("Fe_magmoms_collinear_GSR.tar.xz", [-0.5069359730980665]), + ("Fe_magmoms_noncollinear_GSR.tar.xz", [[0.357939487, 0.357939487, 0]]), + ], + ) + def test_read_fe(self, tarname, expected): + with tarfile.open(os.path.join(TEST_DIR, tarname), mode="r:xz") as t: # TODO: remove attr check after only 3.12+ if hasattr(tarfile, "data_filter"): t.extractall(".", filter="data") else: t.extractall(".") # noqa: S202 - ref_magmom_collinear = [-0.5069359730980665] - path = os.path.join(".", "Fe_magmoms_collinear_GSR.nc") - - # TODO: PR4128, EtsfReader would fail in Ubuntu CI with netCDF4 > 1.6.5 - # Need someone with knowledge in netCDF4 to fix it - with EtsfReader(path) as data: - structure = data.read_structure() - assert structure.site_properties["magmom"] == ref_magmom_collinear - - with tarfile.open(f"{TEST_DIR}/Fe_magmoms_noncollinear_GSR.tar.xz", mode="r:xz") as t: - # TODO: remove attr check after only 3.12+ - if hasattr(tarfile, "data_filter"): - t.extractall(".", filter="data") - else: - t.extractall(".") # noqa: S202 - ref_magmom_noncollinear = [[0.357939487, 0.357939487, 0]] - path = os.path.join(".", "Fe_magmoms_noncollinear_GSR.nc") + path = os.path.basename(tarname).replace(".tar.xz", ".nc") with EtsfReader(path) as data: structure = data.read_structure() - assert structure.site_properties["magmom"] == ref_magmom_noncollinear + assert structure.site_properties["magmom"] == expected class TestAbinitHeader(MatSciTest): From a9ff0be8f84da63c29eab3162be7c9fcb6d3b218 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Thu, 9 Oct 2025 12:09:00 +0200 Subject: [PATCH 4/4] test and build Python 3.14 wheels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fail back to 3.13 for lint as pyright is not installable revert win to 3.11 for now (cannot recreate locally) resolve to highest in Ubuntu fix different err msg in 3.14 ➜ temp uv run -p 3.13 test_index.py Traceback (most recent call last): File "/Users/yang/developer/temp/test_index.py", line 1, in print(["a"].index(1)) ~~~~~~~~~~~^^^ ValueError: 1 is not in list ➜ temp uv run -p 3.14 test_index.py Traceback (most recent call last): File "/Users/yang/developer/temp/test_index.py", line 1, in print(["a"].index(1)) ~~~~~~~~~~~^^^ ValueError: list.index(x): x not in list skip netcdf4 in 3.13 skip more py 3.14 incompatible deps matcalc seems installable on python 3.13 and 3.14 skip more packages that doesn't support 3.14 now remove pin for pure python analysis-alloy remove comment drop openai pin unblock h5py unpin netcdf4 --- .github/workflows/lint.yml | 4 +++- .github/workflows/release.yml | 6 ++--- .github/workflows/test.yml | 20 ++++++++--------- pyproject.toml | 7 +++--- tests/io/vasp/test_outputs.py | 2 +- uv.lock | 42 +++++++++++++++++------------------ 6 files changed, 42 insertions(+), 39 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 752a4884da4..f69f0046a11 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -14,12 +14,14 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 + - name: Install uv with python version. uses: astral-sh/setup-uv@v6 with: - python-version: "3.11" + python-version: "3.13" enable-cache: true cache-dependency-glob: "uv.lock" + - name: Install dependencies run: | uv sync diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8a3ca03227e..56b3483f55c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -30,7 +30,7 @@ jobs: - name: Install Python uses: actions/setup-python@v6 with: - python-version: "3.13" + python-version: "3.14" - name: Build source distribution run: | @@ -47,7 +47,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest, macos-13, windows-latest, ubuntu-24.04-arm] - python-version: ["310", "311", "312", "313"] + python-version: ["310", "311", "312", "313", "314"] runs-on: ${{ matrix.os }} steps: - name: Check out repo @@ -77,7 +77,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v6 with: - python-version: "3.13" + python-version: "3.14" - name: Get build artifacts uses: actions/download-artifact@v5 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a97318919a2..7e7fbf8c352 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -39,26 +39,26 @@ 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.10) on windows (seems most likely to surface errors) and with - # newest version (currently 3.13) on ubuntu (to get complete coverage on unix). + # 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 on windows (most likely to surface errors) and with + # newest version on Ubuntu (to get complete coverage). config: - os: windows-latest - python: "3.10" - resolution: highest + python: "3.10" # Test lowest supported Python version + resolution: lowest-direct extras: optional,prototypes - os: windows-latest python: "3.11" resolution: highest extras: prototypes,optional,numpy-v1 # Test NP1 on Windows (quite buggy ATM) - os: macos-latest - python: "3.12" + python: "3.13" resolution: lowest-direct extras: prototypes # test with only required dependencies installed - os: ubuntu-latest - python: "3.13" - resolution: lowest-direct + python: "3.14" # Test highest supported Python version + resolution: highest extras: prototypes,optional # pytest-split automatically distributes work load so parallel jobs finish in similar time @@ -67,7 +67,7 @@ jobs: runs-on: ${{ matrix.config.os }} env: - OPT_BIN_DIR: ${{ github.workspace }}/opt/bin # for optional Unix dependencies + OPT_BIN_DIR: ${{ github.workspace }}/opt/bin # for optional Ubuntu dependencies steps: - name: Check out repo uses: actions/checkout@v5 diff --git a/pyproject.toml b/pyproject.toml index 769472cd552..f0483390642 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,6 +49,7 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: Scientific/Engineering :: Chemistry", "Topic :: Scientific/Engineering :: Information Analysis", "Topic :: Scientific/Engineering :: Physics", @@ -100,7 +101,7 @@ matcalc = [ "matgl>=1.2.7; python_version<'3.13'", ] mlp = ["matgl>=1.2.7 ; python_version<'3.13'"] -numba = ["numba>=0.55"] +numba = ["numba>=0.55; python_version<'3.14'"] numpy-v1 = ["numpy>=1.25.0,<2"] # Test NP1 on Windows (quite buggy ATM) optional = [ "pymatgen[abinit,ase,matcalc,mlp,tblite,zeopp]", @@ -112,7 +113,7 @@ optional = [ "f90nml>=1.1.2", "galore>=0.6.1", "h5py>=3.11.0", - "hiphive>=1.3.1", + "hiphive>=1.3.1; python_version<'3.14'", "jarvis-tools>=2020.7.14", "phonopy>=2.33.3", "seekpath>=2.0.1", @@ -123,7 +124,7 @@ symmetry = ["moyopy[interface]>=0.3", "spglib>=2.5"] # tblite only support Python 3.12+ through conda-forge # https://github.com/tblite/tblite/issues/175 tblite = ["tblite[ase]>=0.3.0; platform_system=='Linux' and python_version<'3.12'"] -vis = ["vtk>=6.0.0"] +vis = ["vtk>=6.0.0; python_version<'3.14'"] zeopp = ["pyzeo; platform_system != 'Windows'"] # Note: requires Voro++ and Zeo++ to be installed [project.scripts] diff --git a/tests/io/vasp/test_outputs.py b/tests/io/vasp/test_outputs.py index 649dd418ecf..9c1f83ed320 100644 --- a/tests/io/vasp/test_outputs.py +++ b/tests/io/vasp/test_outputs.py @@ -1782,7 +1782,7 @@ def test_init(self): assert procar.get_occupation(0, "d")[Spin.up] == approx(0) assert procar.get_occupation(0, "s")[Spin.up] == approx(0.35381249999999997) assert procar.get_occupation(0, "p")[Spin.up] == approx(1.19540625) - with pytest.raises(ValueError, match="'m' is not in list"): + with pytest.raises(ValueError, match="not in list"): procar.get_occupation(1, "m") assert procar.nbands == 10 assert procar.nkpoints == 10 diff --git a/uv.lock b/uv.lock index 160d0b2dfe6..2f9e520a870 100644 --- a/uv.lock +++ b/uv.lock @@ -1266,16 +1266,16 @@ name = "hiphive" version = "1.5" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "ase" }, - { name = "h5py" }, - { name = "numba" }, - { name = "numpy" }, - { name = "pandas" }, + { name = "ase", marker = "python_full_version < '3.14'" }, + { name = "h5py", marker = "python_full_version < '3.14'" }, + { name = "numba", marker = "python_full_version < '3.14'" }, + { name = "numpy", marker = "python_full_version < '3.14'" }, + { name = "pandas", marker = "python_full_version < '3.14'" }, { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "scipy", version = "1.16.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, - { name = "spglib" }, - { name = "sympy" }, - { name = "trainstation" }, + { name = "scipy", version = "1.16.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11' and python_full_version < '3.14'" }, + { name = "spglib", marker = "python_full_version < '3.14'" }, + { name = "sympy", marker = "python_full_version < '3.14'" }, + { name = "trainstation", marker = "python_full_version < '3.14'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/16/6a/697642c91eafefc253109114c2f8f69d39c997272f140e750c148e330859/hiphive-1.5.tar.gz", hash = "sha256:a8162686265aed88cfa6ad2721f39629102525100879484530cb7c25269ac386", size = 71384, upload-time = "2025-07-28T21:50:13.544Z" } wheels = [ @@ -2764,8 +2764,8 @@ name = "numba" version = "0.61.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "llvmlite" }, - { name = "numpy" }, + { name = "llvmlite", marker = "python_full_version < '3.14'" }, + { name = "numpy", marker = "python_full_version < '3.14'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/1c/a0/e21f57604304aa03ebb8e098429222722ad99176a4f979d34af1d1ee80da/numba-0.61.2.tar.gz", hash = "sha256:8750ee147940a6637b80ecf7f95062185ad8726c8c28a2295b8ec1160a196f7d", size = 2820615, upload-time = "2025-04-09T02:58:07.659Z" } wheels = [ @@ -3668,7 +3668,7 @@ mlp = [ { name = "matgl", marker = "python_full_version < '3.13'" }, ] numba = [ - { name = "numba" }, + { name = "numba", marker = "python_full_version < '3.14'" }, ] numpy-v1 = [ { name = "numpy" }, @@ -3680,7 +3680,7 @@ optional = [ { name = "f90nml" }, { name = "galore" }, { name = "h5py" }, - { name = "hiphive" }, + { name = "hiphive", marker = "python_full_version < '3.14'" }, { name = "jarvis-tools" }, { name = "matcalc", marker = "python_full_version < '3.13'" }, { name = "matgl", marker = "python_full_version < '3.13'" }, @@ -3704,7 +3704,7 @@ tblite = [ { name = "tblite", extra = ["ase"], marker = "python_full_version < '3.12' and sys_platform == 'linux'" }, ] vis = [ - { name = "vtk" }, + { name = "vtk", marker = "python_full_version < '3.14'" }, ] zeopp = [ { name = "pyzeo", marker = "sys_platform != 'win32'" }, @@ -3744,7 +3744,7 @@ requires-dist = [ { name = "f90nml", marker = "extra == 'optional'", specifier = ">=1.1.2" }, { name = "galore", marker = "extra == 'optional'", specifier = ">=0.6.1" }, { name = "h5py", marker = "extra == 'optional'", specifier = ">=3.11.0" }, - { name = "hiphive", marker = "extra == 'optional'", specifier = ">=1.3.1" }, + { name = "hiphive", marker = "python_full_version < '3.14' and extra == 'optional'", specifier = ">=1.3.1" }, { name = "jarvis-tools", marker = "extra == 'optional'", specifier = ">=2020.7.14" }, { name = "joblib", specifier = ">=1" }, { name = "matcalc", marker = "python_full_version < '3.13' and extra == 'matcalc'", specifier = ">=0.4.0" }, @@ -3755,7 +3755,7 @@ requires-dist = [ { name = "moyopy", extras = ["interface"], marker = "extra == 'symmetry'", specifier = ">=0.3" }, { name = "netcdf4", marker = "extra == 'abinit'", specifier = ">=1.7.2" }, { name = "networkx", specifier = ">=2.7" }, - { name = "numba", marker = "extra == 'numba'", specifier = ">=0.55" }, + { name = "numba", marker = "python_full_version < '3.14' and extra == 'numba'", specifier = ">=0.55" }, { name = "numpy", specifier = ">=1.25.0,<3" }, { name = "numpy", marker = "extra == 'numpy-v1'", specifier = ">=1.25.0,<2" }, { name = "orjson", specifier = ">=3.10,<4" }, @@ -3780,7 +3780,7 @@ requires-dist = [ { name = "tblite", extras = ["ase"], marker = "python_full_version < '3.12' and sys_platform == 'linux' and extra == 'tblite'", specifier = ">=0.3.0" }, { name = "tqdm", specifier = ">=4.60" }, { name = "uncertainties", specifier = ">=3.1.4" }, - { name = "vtk", marker = "extra == 'vis'", specifier = ">=6.0.0" }, + { name = "vtk", marker = "python_full_version < '3.14' and extra == 'vis'", specifier = ">=6.0.0" }, ] provides-extras = ["abinit", "ase", "matcalc", "mlp", "numba", "numpy-v1", "optional", "prototypes", "symmetry", "tblite", "vis", "zeopp"] @@ -5269,10 +5269,10 @@ name = "trainstation" version = "1.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "numpy" }, - { name = "scikit-learn" }, + { name = "numpy", marker = "python_full_version < '3.14'" }, + { name = "scikit-learn", marker = "python_full_version < '3.14'" }, { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "scipy", version = "1.16.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "scipy", version = "1.16.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11' and python_full_version < '3.14'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/94/bc/674edf4fb12f40d9b626b99a994c9d8281a5d0d327ceb8239c62bdd750d9/trainstation-1.2.tar.gz", hash = "sha256:e2cda1716a09f98930aa34640bdb2ac05e49e675afe54979d81657f3fac37d9b", size = 28509, upload-time = "2025-07-30T08:32:19.603Z" } wheels = [ @@ -5414,7 +5414,7 @@ name = "vtk" version = "9.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "matplotlib" }, + { name = "matplotlib", marker = "python_full_version < '3.14'" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/72/f5/3c4ff853eed6945a2a1f2ae3426a5faa7fee1b2f1a8eb007e369ad56c2cc/vtk-9.5.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:f9ed7461707bc2b5b2cca6eb3a749de82269ba632ab39a5e0f3b55e3d5002ff8", size = 86778960, upload-time = "2025-06-24T09:40:18.892Z" },