diff --git a/.github/workflows/build_upload_pypi_wheels.yml b/.github/workflows/build_upload_pypi_wheels.yml index aa8d6a660..7243bd3f0 100644 --- a/.github/workflows/build_upload_pypi_wheels.yml +++ b/.github/workflows/build_upload_pypi_wheels.yml @@ -89,8 +89,8 @@ jobs: CIBW_REPAIR_WHEEL_COMMAND_MACOS: "" - CIBW_TEST_EXTRAS: "test,brille,phonopy_reader,matplotlib" - CIBW_TEST_COMMAND: "python {package}/tests_and_analysis/test/run_tests.py" + CIBW_TEST_EXTRAS: "test,brille,phonopy-reader,matplotlib" + CIBW_TEST_COMMAND: python {package}/tests_and_analysis/test/run_tests.py with: output-dir: wheelhouse @@ -169,7 +169,7 @@ jobs: - name: Install from sdist shell: bash -l {0} - run: python -m pip install $(find dist -name 'euphonic-*.tar.gz')[matplotlib,phonopy_reader,brille,test] + run: python -m pip install $(find dist -name 'euphonic-*.tar.gz')[matplotlib,phonopy-reader,brille,test] - name: Checkout repository (for tests and test data) uses: actions/checkout@v4 diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index d668cbd1d..374c64a6f 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -73,16 +73,13 @@ jobs: if: github.event_name != 'workflow_dispatch' env: TOX_SKIP_ENV: '.*?(py311).*?' - TOX_PARALLEL_NO_SPINNER: 1 shell: bash -l {0} - run: python -m tox --parallel + run: python -m tox run-parallel - name: Run tests, workflow dispatch so test all Python versions if: github.event_name == 'workflow_dispatch' - env: - TOX_PARALLEL_NO_SPINNER: 1 shell: bash -l {0} - run: python -m tox --parallel + run: python -m tox run-parallel - name: Upload test results if: always() @@ -115,7 +112,7 @@ jobs: python -m pip install --upgrade pip python -m pip install -r tests_and_analysis/ci_requirements.txt python -m pip install -r doc/requirements.txt - python -m pip install .[matplotlib,phonopy_reader,brille] + python -m pip install .[matplotlib,phonopy-reader,brille] - name: Run Sphinx doctests working-directory: ./doc shell: bash -l {0} diff --git a/.github/workflows/test_release.yml b/.github/workflows/test_release.yml index b66179bf9..ee61504eb 100644 --- a/.github/workflows/test_release.yml +++ b/.github/workflows/test_release.yml @@ -15,12 +15,15 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - - uses: conda-incubator/setup-miniconda@v3 with: - python-version: '3.10' - channels: conda-forge,defaults - channel-priority: true - - name: Install llvm on Macos + fetch-depth: 0 # Ensure tags are fetched for versioning + - uses: actions/setup-python@v5 + with: + python-version: | + 3.10 + 3.11 + 3.12 + - name: Install llvm on MacOS if: startsWith(matrix.os, 'macos') shell: bash -l {0} env: diff --git a/.readthedocs.yml b/.readthedocs.yml index 8ec0978d5..b527e5116 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -23,5 +23,5 @@ python: path: . extra_requirements: - matplotlib - - phonopy_reader + - phonopy-reader - brille diff --git a/build_utils/release_tox.ini b/build_utils/release_tox.ini index 5c8a300a7..0ed260e2b 100644 --- a/build_utils/release_tox.ini +++ b/build_utils/release_tox.ini @@ -1,74 +1,52 @@ [tox] # Use conda to set up the python environments to run in -requires = tox-conda +requires = tox>=4 # The python environments to run the tests in envlist = pypi-py310-min,conda-py310-old-np,{pypi,conda}-{py310,py311,py312},pypisource-{py310,py312} -# Skip the execution of setup.py as we do it with the correct version in commands_pre below -skipsdist = True +skip_install = True [testenv] changedir = tests_and_analysis/test test_command = python {toxinidir}/../tests_and_analysis/test/run_tests.py --report requirements_dir = {toxinidir}/../tests_and_analysis +passenv = + EUPHONIC_VERSION +# The name "extras" is reserved and has its own format with newlines: +# we need a token to inject into custom commands_pre, so call it extras_str +extras_str = [test,matplotlib,phonopy-reader,brille] # Test PyPI source distribution [testenv:pypisource-{py310,py312}] -passenv = CC CC_LD LDFLAGS CPPFLAGS -install_command = python -m pip install {opts} {packages} -deps = - numpy - spglib # Not interested here in whether source builds of spglib work - -r{[testenv]requirements_dir}/tox_requirements.txt +passenv = + CC + CC_LD + LDFLAGS + CPPFLAGS commands_pre = python -m pip install \ --force-reinstall \ - 'euphonic[matplotlib,phonopy_reader,brille]=={env:EUPHONIC_VERSION}' \ + euphonic{[testenv]extras_str}=={env:EUPHONIC_VERSION} \ --no-binary 'euphonic' commands = {[testenv]test_command} - [testenv:pypi-{py310,py311,py312}] -install_command = python -m pip install {opts} {packages} -deps = - numpy - -r{[testenv]requirements_dir}/tox_requirements.txt commands_pre = python -m pip install \ --force-reinstall \ - 'euphonic[matplotlib,phonopy_reader,brille]=={env:EUPHONIC_VERSION}' \ + euphonic{[testenv]extras_str}=={env:EUPHONIC_VERSION} \ --only-binary 'euphonic' commands = {[testenv]test_command} -[testenv:pypi-py310-min-win-linux] -install_command = python -m pip install --force-reinstall {opts} {packages} -platform = - linux: linux - windows: win32 +[testenv:pypi-py310-min] +platform = (linux)|(win32) deps = - numpy==1.24.0 + numpy==1.24 + -r{toxinidir}/../tests_and_analysis/tox_requirements.txt commands_pre = python -m pip install --force-reinstall \ - -r{[testenv]requirements_dir}/minimum_euphonic_requirements.txt - python -m pip install --force-reinstall \ - -r{[testenv]requirements_dir}/tox_requirements.txt + -r{toxinidir}/../tests_and_analysis/minimum_euphonic_requirements.txt python -m pip install \ - 'euphonic[matplotlib,phonopy_reader,brille]=={env:EUPHONIC_VERSION}' \ - --only-binary 'euphonic' -commands = {[testenv]test_command} - -[testenv:pypi-py310-min-mac] -install_command = python -m pip install --force-reinstall {opts} {packages} -platform = - mac: darwin -deps = - numpy==1.24.0 -commands_pre = - python -m pip install --force-reinstall \ - -r{[testenv]requirements_dir}/minimum_euphonic_requirements_mac.txt - python -m pip install --force-reinstall \ - -r{[testenv]requirements_dir}/tox_requirements.txt - python -m pip install \ - 'euphonic[matplotlib,phonopy_reader,brille]=={env:EUPHONIC_VERSION}' \ + euphonic{[testenv]extras_str}=={env:EUPHONIC_VERSION} \ --only-binary 'euphonic' commands = {[testenv]test_command} @@ -78,10 +56,13 @@ install_command = conda install {packages} conda_channels = conda-forge default -conda_deps = - --file={[testenv]requirements_dir}/tox_requirements.txt +extras = + test + matplotlib + phonopy-reader + commands_pre = - conda install -c conda-forge euphonic={env:EUPHONIC_VERSION} matplotlib-base pyyaml h5py + conda install -c conda-forge euphonic={env:EUPHONIC_VERSION} # Brille not available on conda commands = {[testenv]test_command} -m "not brille" @@ -93,10 +74,12 @@ install_command = conda install {packages} conda_channels = conda-forge default -conda_deps = - --file={[testenv]requirements_dir}/tox_requirements.txt +deps = numpy==1.24 +extras = + test + matplotlib + phonopy-reader commands_pre = - conda install numpy=1.22 - conda install -c conda-forge euphonic={env:EUPHONIC_VERSION} matplotlib-base pyyaml h5py + conda install -c conda-forge euphonic={env:EUPHONIC_VERSION} # Brille not available on conda commands = {[testenv]test_command} -m "not brille" diff --git a/doc/source/installation.rst b/doc/source/installation.rst index 0682f9ff8..4bc67eea1 100644 --- a/doc/source/installation.rst +++ b/doc/source/installation.rst @@ -14,14 +14,14 @@ Euphonic has optional 'extensions' which require extra dependencies for certain They are listed below * **matplotlib** - required for plotting -* **phonopy_reader** - required for reading Phonopy files +* **phonopy-reader** - required for reading Phonopy files * **brille** - required for performing linear interpolation with the Brille library To install euphonic with all the dependencies run: .. code-block:: bash - pip install euphonic[matplotlib,phonopy_reader,brille] + pip install euphonic[matplotlib,phonopy-reader,brille] The dependencies can also be installed individually: @@ -69,7 +69,7 @@ To install with all dependencies use: .. code-block:: bash - pip install .[matplotlib,phonopy_reader,brille] + pip install .[matplotlib,phonopy-reader,brille] If you don't require the extra dependencies, just use: diff --git a/euphonic/readers/phonopy.py b/euphonic/readers/phonopy.py index b1b0bc980..09c68ce50 100644 --- a/euphonic/readers/phonopy.py +++ b/euphonic/readers/phonopy.py @@ -18,7 +18,7 @@ def __init__(self): '\n\nCannot import yaml, h5py to read Phonopy files, maybe ' 'they are not installed. To install the optional ' 'dependencies for Euphonic\'s Phonopy reader, try:\n\n' - 'pip install euphonic[phonopy_reader]\n') + 'pip install euphonic[phonopy-reader]\n') def __str__(self): return self.message diff --git a/pyproject.toml b/pyproject.toml index 6aec791d4..dc1ade576 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,9 +53,11 @@ documentation = "https://euphonic.readthedocs.io/en/stable/" [project.optional-dependencies] matplotlib = ["matplotlib>=3.8.0"] -phonopy_reader = ["h5py>=3.6.0", "PyYAML>=6.0"] +phonopy_reader = ["h5py>=3.6.0", "PyYAML>=6.0"] # Deprecated, will be removed in future versions. +phonopy-reader = ["h5py>=3.6.0", "PyYAML>=6.0"] brille = ["brille>=0.7.0"] -test = ["mock", "pytest~=7.0", "coverage", "pytest-mock", "pytest-lazy-fixture", "pytest-xvfb"] +test = ["mock", "pytest~=7.0", "coverage", "pytest-mock", "pytest-lazy-fixture", "pytest-xvfb", "python-slugify"] +ci = ["tox==4.32.2"] [project.scripts] euphonic-brille-convergence = "euphonic.cli.brille_convergence:main" diff --git a/tests_and_analysis/ci_requirements.txt b/tests_and_analysis/ci_requirements.txt index cea4f609d..974751142 100644 --- a/tests_and_analysis/ci_requirements.txt +++ b/tests_and_analysis/ci_requirements.txt @@ -1 +1 @@ -tox==3.28.0 +tox==4.23.2 diff --git a/tests_and_analysis/test/euphonic_test/test_force_constants_calculate_qpoint_phonon_modes.py b/tests_and_analysis/test/euphonic_test/test_force_constants_calculate_qpoint_phonon_modes.py index 0462761c5..56abb442c 100644 --- a/tests_and_analysis/test/euphonic_test/test_force_constants_calculate_qpoint_phonon_modes.py +++ b/tests_and_analysis/test/euphonic_test/test_force_constants_calculate_qpoint_phonon_modes.py @@ -301,7 +301,7 @@ def test_with_use_c_false_doesnt_raise_error_or_warn( fc.calculate_qpoint_phonon_modes(get_test_qpts(), use_c=False) assert len(warn_record) == 0 - +@pytest.mark.c_extension class TestForceConstantsCalculateQPointPhononModesWithCExtensionInstalled: @pytest.fixture diff --git a/tests_and_analysis/test/pytest.ini b/tests_and_analysis/test/pytest.ini index 0d0c1f49e..3c72d8828 100644 --- a/tests_and_analysis/test/pytest.ini +++ b/tests_and_analysis/test/pytest.ini @@ -4,3 +4,4 @@ markers = matplotlib: requires euphonic[matplotlib] extra to be installed brille: requires euphonic[brille] extra to be installed multiple_extras: requires any combination of the above extras e.g. phonopy_reader and matplotlib + c_extension: Requires c extension compiled diff --git a/tox.ini b/tox.ini index 1892f9cf5..9a168e3a5 100644 --- a/tox.ini +++ b/tox.ini @@ -1,99 +1,87 @@ [tox] +requires = tox>=4 # The python environments to run the tests in -envlist = py310,py311,py312,py310-{base,matplotlib,phonopy_reader,brille,all},py310-minrequirements-{mac,linux} -# Skip the execution of setup.py as we do it with the correct arg in commands_pre below -skipsdist = True -whitelist_externals = git +envlist = py310,py311,py312,py310-{base,matplotlib,phonopy-reader,brille,all,minrequirements-linux,minrequirements-mac,no-c} +allowlist_externals = git [testenv] +package = wheel changedir = tests_and_analysis/test test_command = python run_tests.py --report -passenv = CC CC_LD LDFLAGS CPPFLAGS - -[testenv:{py310,py311,py312}] +passenv = CC_LD install_command = - python -m pip install \ + python -m pip install -v \ --force-reinstall \ --upgrade \ --upgrade-strategy eager \ {opts} \ {packages} -deps = - numpy - -r{toxinidir}/tests_and_analysis/tox_requirements.txt -commands_pre = - python -m pip install \ - --upgrade \ - --upgrade-strategy eager \ - '{toxinidir}[matplotlib,phonopy_reader,brille]' -commands = - {[testenv]test_command} --cov +extras = + test + +[testenv:{py310,py311,py312}] +extras = + {[testenv]extras} + matplotlib + phonopy-reader + brille +commands = {[testenv]test_command} --cov # Test with no extras [testenv:py310-base] -install_command = {[testenv:py310]install_command} -deps = {[testenv:py310]deps} -commands_pre = - python -m pip install \ - --upgrade \ - --upgrade-strategy eager \ - '{toxinidir}' +extras = {[testenv]extras} commands = {[testenv]test_command} --cov -m "not (phonopy_reader or matplotlib or brille)" # Test with matplotlib extra only [testenv:py310-matplotlib] -install_command = {[testenv:py310]install_command} -deps = {[testenv:py310]deps} -commands_pre = - python -m pip install \ - --upgrade \ - --upgrade-strategy eager \ - '{toxinidir}[matplotlib]' +extras = + {[testenv]extras} + matplotlib commands = {[testenv]test_command} --cov -m "matplotlib and not multiple_extras" -# Test with phonopy_reader extra only -[testenv:py310-phonopy_reader] -install_command = {[testenv:py310]install_command} -deps = {[testenv:py310]deps} -commands_pre = - python -m pip install \ - --upgrade \ - --upgrade-strategy eager \ - '{toxinidir}[phonopy_reader]' +# Test with phonopy-reader extra only +[testenv:py310-phonopy-reader] +extras = + {[testenv]extras} + phonopy-reader commands = {[testenv]test_command} --cov -m "phonopy_reader and not multiple_extras" # Test with brille extra only [testenv:py310-brille] -install_command = {[testenv:py310]install_command} -deps = {[testenv:py310]deps} -commands_pre = - python -m pip install \ - --upgrade \ - --upgrade-strategy eager \ - '{toxinidir}[brille]' +extras = + {[testenv]extras} + brille commands = {[testenv]test_command} --cov -m "brille and not multiple_extras" # Run remaining tests that require multiple extras [testenv:py310-all] -install_command = {[testenv:py310]install_command} -deps = {[testenv:py310]deps} -commands_pre = - python -m pip install \ - --upgrade \ - --upgrade-strategy eager \ - '{toxinidir}[phonopy_reader,matplotlib,brille]' +extras = + {[testenv]extras} + matplotlib + phonopy-reader + brille commands = {[testenv]test_command} --cov -m multiple_extras +[testenv:py310-no-c] +install_command = {[testenv]install_command} -Csetup-args="-Dpython_only=true" +platform = linux +extras = + {[testenv]extras} + matplotlib + phonopy-reader + brille +commands = {[testenv]test_command} -m 'not c_extension' + [testenv:py310-minrequirements-linux] -whitelist_externals = rm +skip_install = True +allowlist_externals = rm install_command = python -m pip install --force-reinstall {opts} {packages} -platform = - linux: linux +platform = linux deps = numpy==1.24.0 - {[testenv:py310]deps} + -r{toxinidir}/tests_and_analysis/tox_requirements.txt commands_pre = python -m pip install --force-reinstall \ -r{toxinidir}/tests_and_analysis/minimum_euphonic_requirements.txt @@ -101,18 +89,18 @@ commands_pre = -r{toxinidir}/tests_and_analysis/tox_requirements.txt # Force rebuild of euphonic extension to avoid Numpy clash rm -rf {toxinidir}/build - python -m pip install '{toxinidir}[matplotlib,phonopy_reader,brille]' + python -m pip install '{toxinidir}[matplotlib,phonopy-reader,brille]' commands = {[testenv]test_command} [testenv:py310-minrequirements-mac] -whitelist_externals = rm +skip_install = True +allowlist_externals = rm install_command = python -m pip install --force-reinstall {opts} {packages} -platform = - macos: darwin +platform = darwin deps = numpy==1.24.0 - {[testenv:py310]deps} + -r{toxinidir}/tests_and_analysis/tox_requirements.txt commands_pre = python -m pip install --force-reinstall \ -r{toxinidir}/tests_and_analysis/minimum_euphonic_requirements_mac.txt @@ -120,5 +108,5 @@ commands_pre = -r{toxinidir}/tests_and_analysis/tox_requirements.txt # Force rebuild of euphonic extension to avoid Numpy clash rm -rf {toxinidir}/build - python -m pip install '{toxinidir}[matplotlib,phonopy_reader,brille]' + python -m pip install '{toxinidir}[matplotlib,phonopy-reader,brille]' commands = {[testenv]test_command}