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 fb44cbce142..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] @@ -164,10 +165,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*"] @@ -261,7 +258,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] @@ -277,12 +274,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.", 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): 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" },