Skip to content

Commit 554017e

Browse files
authored
Apply some important fixes (#579)
- Use `pyccel >= 2.2.3`: this allows compiling all kernels with C - Require `h5py >= 3.16` to allow for standard install with `setuptools >= 81.0` - Require `numpy >= 2.1` to support Python >= 3.10 - Use `pytest.toml` instead of `pytest.ini` for Pytest configuration (requires `pytest >= 9.0`) - Move coverage configuration from `pyproject.toml` to `psydac/pytest.toml` - Don't run postprocessing unit tests with `pytest-xdist` because `h5py` is not thread-safe: add Pytest mark `@pytest.mark.xdist_group('h5py')` to all unit tests in `psydac/api/tests/test_postprocessing.py` - Return error code on failure of the `psydac test` command; this was not correctly returned before, hence the CI could not detect when the unit tests were failing in a subprocess - Return error code on failure of the `psydac compile` command; this fix does not directly affect the CI, but it is included for correctness. - Check correct reporting of failure for `psydac test` command in CI testing - Use correct configuration file in coverage CI tests - For clarity, rename temporary folder where all CI tests are run: `pytest` -> `scratch` - Clean up `.gitignore`; specifically, stop ignoring files which don't exist anymore
1 parent 16fb9d3 commit 554017e

14 files changed

Lines changed: 176 additions & 118 deletions

File tree

.github/actions/parallel_h5py/action.yml

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,20 @@ runs:
1515
echo $HDF5_DIR
1616
echo "HDF5_DIR=$HDF5_DIR" >> $GITHUB_ENV
1717
18-
# To be deactivated when a new version of h5py is released on PyPI
1918
- name: Install h5py in parallel mode
2019
shell: bash
2120
run: |
2221
export CC="mpicc"
2322
export HDF5_MPI="ON"
24-
git clone https://github.com/h5py/h5py.git
25-
cd h5py
26-
pip install -v .
23+
pip install h5py --no-cache-dir --no-binary h5py
2724
pip list
2825
29-
# To be reactivated when a new version of h5py is released on PyPI
30-
# - name: Install h5py in parallel mode
31-
# shell: bash
32-
# run: |
33-
# export CC="mpicc"
34-
# export HDF5_MPI="ON"
35-
# pip install h5py --no-cache-dir --no-binary h5py
36-
# pip list
37-
3826
- name: Check parallel h5py installation
3927
shell: bash
4028
run: |
41-
python -c "
42-
from mpi4py import MPI
43-
import h5py
44-
# This particular instantiation of h5py.File will fail if parallel h5py isn't installed
45-
f = h5py.File('parallel_test.hdf5', 'w', driver='mpio', comm=MPI.COMM_WORLD)
46-
print(f)"
29+
python -c "
30+
from mpi4py import MPI
31+
import h5py
32+
# This particular instantiation of h5py.File will fail if parallel h5py isn't installed
33+
f = h5py.File('parallel_test.hdf5', 'w', driver='mpio', comm=MPI.COMM_WORLD)
34+
print(f)"

.github/workflows/testing.yml

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ on:
88
branches: [ devel, main ]
99
paths:
1010
- 'psydac/**'
11-
- 'pytest.ini'
1211
- 'pyproject.toml'
1312

1413
pull_request:
@@ -119,27 +118,37 @@ jobs:
119118
pip install .[test]
120119
pip freeze
121120
122-
- name: Test Pyccel optimization flags
121+
- name: Initialize test directory
123122
run: |
123+
mkdir scratch
124+
125+
- name: Test Pyccel optimization flags
126+
working-directory: ./scratch
127+
run: >-
128+
cp $GITHUB_WORKSPACE/psydac/pytest.toml . &&
124129
pytest --pyargs psydac -m pyccel --capture=no
125130
126-
- name: Initialize test directory
131+
- name: Verify that 'psydac test' reports failures correctly
132+
working-directory: ./scratch
133+
# We run a test which is not collected by pytest by default, and we expect it to fail.
134+
# If it fails (non-zero), the "echo" runs and the script exits with 0 (success).
135+
# If it passes (zero), the "exit 1" runs and the GitHub Action fails.
127136
run: |
128-
mkdir pytest
137+
psydac test --mod psydac.cmd.tests.failing_test && { echo "Test passed but should have failed!"; exit 1; } || echo "Test failed as expected."
129138
130139
- name: Run coverage tests on macOS
131140
if: matrix.os == 'macos-14'
132-
working-directory: ./pytest
141+
working-directory: ./scratch
133142
run: >-
143+
cp $GITHUB_WORKSPACE/psydac/pytest.toml . &&
134144
pytest -n auto
135145
--cov psydac
136-
--cov-config $GITHUB_WORKSPACE/pyproject.toml
137146
--cov-report xml
138147
--pyargs psydac -m "not mpi and not petsc" -ra
139148
140149
- name: Run single-process tests with Pytest on Ubuntu
141150
if: matrix.os == 'ubuntu-24.04'
142-
working-directory: ./pytest
151+
working-directory: ./scratch
143152
run: |
144153
psydac test
145154
@@ -148,35 +157,38 @@ jobs:
148157
uses: codacy/codacy-coverage-reporter-action@v1.3.0
149158
with:
150159
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
151-
coverage-reports: ./pytest/coverage.xml
160+
coverage-reports: ./scratch/coverage.xml
152161

153162
- name: Print detailed coverage results on macOS
154163
if: matrix.os == 'macos-14'
155-
working-directory: ./pytest
164+
working-directory: ./scratch
156165
run: |
157166
coverage report --ignore-errors --show-missing --sort=cover
158167
159168
- name: Run MPI tests with Pytest
160-
working-directory: ./pytest
169+
working-directory: ./scratch
161170
run: |
162171
psydac test --mpi
163172
164173
- name: Run single-process PETSc tests with Pytest
165-
working-directory: ./pytest
174+
working-directory: ./scratch
166175
run: |
167176
psydac test --petsc
168177
169178
- name: Run MPI PETSc tests with Pytest
170-
working-directory: ./pytest
179+
working-directory: ./scratch
171180
run: |
172181
psydac test --mpi --petsc
173182
174183
- name: Run single-process example tests with Pytest on Ubuntu
175184
if: matrix.os == 'ubuntu-24.04'
176-
run: |
185+
working-directory: ./scratch
186+
run: >-
187+
cp $GITHUB_WORKSPACE/psydac/pytest.toml . &&
188+
cp -r $GITHUB_WORKSPACE/examples . &&
177189
python -m pytest examples/feec
178190
179191
- name: Remove test directory
180192
if: always()
181193
run: |
182-
rm -rf pytest
194+
rm -rf scratch

.gitignore

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,20 @@ build
1111
*build*
1212
*egg*
1313
*dist*
14-
usr
1514
*cache*
1615

1716
*.swp
1817
*.log
1918

20-
doc/_static
21-
doc/_build
22-
doc/api-python
23-
24-
psydac/core/bsp-f2py*
25-
psydac/core/bspmodule.c
26-
.env
27-
2819
# pytest directories
2920
__test__/
3021

3122
# pycharm directory
3223
.idea
3324

34-
# Visual Studio Code workspace files
25+
# Visual Studio Code
3526
*.code-workspace
27+
**/.vscode/
3628

3729
# Meson lock files
3830
*/.wraplock

CHANGELOG.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,24 @@ All notable changes to this project will be documented in this file.
1010

1111
### Fixed
1212

13+
- #579 : Require `h5py>=3.16` which installs correctly with `setuptools>=81.0`
14+
- #579 : Don't run postprocessing unit tests with `pytest-xdist` because `h5py` is not thread-safe
15+
- #579 : Return error code on failure of the `psydac test` and `psydac compile` commands
1316
- #577 : Fix installation following release of Pyccel 2.2
1417
- #571 : Fix correct application of the sum factorization algorithm
1518
- #570 : Optimize PSYDAC logo
1619
- #565 : Expand editable install info in `README.md`
1720
- #566 : Fix command `psydac test --mpi` on Ubuntu machines
18-
- [DEVELOPER] Update CI installation of `h5py` and `petsc4py` after release of `setuptools` 81.0
21+
- [DEVELOPER] Update CI installation of `petsc4py` after release of `setuptools` 81.0
22+
- [DEVELOPER] Check correct reporting of failure for `psydac test` command in CI testing
23+
- [DEVELOPER] Use correct configuration file in coverage CI tests
1924

2025
### Changed
2126

27+
- #579 : Require `pyccel>=2.2.3` which can compile all kernels with C
28+
- #579 : Require `numpy>=2.1` to support Python >= 3.10
29+
- #579 : Require `pytest>=9.0` and use `pytest.toml` instead of `pytest.ini` for Pytest configuration
30+
- #579 : Move coverage configuration from `pyproject.toml` to `psydac/pytest.toml`
2231
- [DEVELOPER] Do not check file changes to trigger testing workflow on PRs
2332
- [DEVELOPER] Run documentation workflow on pushes to `devel` whenever `README.md` is modified
2433
- [DEVELOPER] Run testing and documentation workflows on PRs only when set to "ready for review"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ A developer wanting to modify the latest source code on GitHub should skip that
6464
git clone --recurse-submodules https://github.com/pyccel/psydac.git
6565
cd psydac
6666

67-
pip install meson-python "pyccel>=2.2.2"
67+
pip install meson-python "pyccel>=2.2.3"
6868
pip install --no-build-isolation --editable ".[test]"
6969
```
7070

docs/installation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ At this point the PSYDAC library may be installed from PyPI in **standard mode**
149149
git clone --recurse-submodules https://github.com/pyccel/psydac.git
150150
cd psydac
151151
152-
pip install meson-python "pyccel>=2.1.0"
152+
pip install meson-python "pyccel>=2.2.3"
153153
pip install --no-build-isolation --editable ".[test]"
154154
```
155155
An equivalent repository address for the `clone` command is `git@github.com:pyccel/psydac.git`, which requires a GitHub account.

psydac/api/tests/test_postprocessing.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ def build_2_cubes():
8282
###############################################################################
8383
# Output Manager tests #
8484
###############################################################################
85+
@pytest.mark.xdist_group('h5py')
8586
@pytest.mark.parametrize( 'dtype', ['float', 'complex'] )
8687
def test_add_spaces(dtype):
8788
domain = Square('D')
@@ -206,6 +207,7 @@ def test_add_spaces(dtype):
206207
os.remove('test_add_spaces_single_patch.yml')
207208

208209

210+
@pytest.mark.xdist_group('h5py')
209211
@pytest.mark.parametrize( 'dtype', ['float', 'complex'] )
210212
def test_export_fields_serial(dtype):
211213
domain = Square('D')
@@ -287,6 +289,7 @@ def test_export_fields_serial(dtype):
287289
os.remove('test_export_fields_serial.h5')
288290

289291

292+
@pytest.mark.xdist_group('h5py')
290293
@pytest.mark.mpi
291294
def test_export_fields_parallel():
292295
comm = MPI.COMM_WORLD
@@ -329,6 +332,7 @@ def test_export_fields_parallel():
329332
###############################################################################
330333
# Output Manager and PostProcess Manager tests #
331334
###############################################################################
335+
@pytest.mark.xdist_group('h5py')
332336
@pytest.mark.parametrize('domain', [Square(), Cube()])
333337
@pytest.mark.parametrize( 'dtype', ['float', 'complex'] )
334338
def test_reconstruct_spaces_topological_domain(domain, dtype):
@@ -398,6 +402,7 @@ def test_reconstruct_spaces_topological_domain(domain, dtype):
398402
os.remove("test_reconstruct_spaces_topological_domain_2.yml")
399403

400404

405+
@pytest.mark.xdist_group('h5py')
401406
@pytest.mark.parametrize('domain, seq', [(Square(), ['h1', 'hdiv', 'l2']), (Square(), ['h1', 'hcurl', 'l2']), (Cube(), None)])
402407
@pytest.mark.parametrize( 'dtype', ['float', 'complex'] )
403408
def test_reconstruct_DerhamSequence_topological_domain(domain, seq, dtype):
@@ -456,6 +461,7 @@ def test_reconstruct_DerhamSequence_topological_domain(domain, seq, dtype):
456461
os.remove('test_reconstruct_DerhamSequence_topological_domain.yml')
457462

458463

464+
@pytest.mark.xdist_group('h5py')
459465
@pytest.mark.parametrize('geometry, seq', [('identity_2d.h5', ['h1', 'hdiv', 'l2']),
460466
('identity_2d.h5', ['h1', 'hcurl', 'l2']),
461467
('identity_3d.h5', None),
@@ -521,6 +527,8 @@ def test_reconstruct_DerhamSequence_discrete_domain(geometry, seq, dtype):
521527
os.remove('test_reconstruct_DerhamSequence_discrete_domain_2.yml')
522528
os.remove('test_reconstruct_DerhamSequence_discrete_domain.yml')
523529

530+
531+
@pytest.mark.xdist_group('h5py')
524532
@pytest.mark.parametrize( 'dtype', ['float', 'complex'] )
525533
def test_reconstruct_multipatch(dtype):
526534
bounds1 = (0.5, 1.)
@@ -602,6 +610,7 @@ def test_reconstruct_multipatch(dtype):
602610
assert value1 == value2
603611

604612

613+
@pytest.mark.xdist_group('h5py')
605614
def test_incorrect_arg_export_to_vtk():
606615
domain = Square()
607616
space = ScalarFunctionSpace('V', domain)
@@ -646,6 +655,7 @@ def test_incorrect_arg_export_to_vtk():
646655
os.remove("test_incorrect_arg_export_to_vtk.h5")
647656

648657

658+
@pytest.mark.xdist_group('h5py')
649659
@pytest.mark.mpi
650660
@pytest.mark.parametrize('geometry', ['identity_2d.h5',
651661
'identity_3d.h5',
@@ -756,6 +766,7 @@ def test_parallel_export_discrete_domain(geometry, kind, space, dtype):
756766
os.remove("test_parallel_export_discrete_domain.h5")
757767

758768

769+
@pytest.mark.xdist_group('h5py')
759770
@pytest.mark.mpi
760771
@pytest.mark.parametrize('domain', [
761772
Square(),

psydac/cmd/psydac_compile.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
The purpose of this module is to pyccelize all PSYDAC kernels, in the case
88
that these were modified after an editable installation of PSYDAC.
99
"""
10-
from psydac.cmd.argparse_helpers import add_help_flag, add_version_flag
10+
from psydac.cmd.argparse_helpers import (
11+
add_help_flag,
12+
add_version_flag,
13+
exit_with_error_message,
14+
)
1115

1216
__all__ = (
1317
'setup_psydac_compile_parser',
@@ -72,4 +76,7 @@ def psydac_compile(*, language):
7276

7377
print('Executing command:')
7478
print(f' {" ".join(cmd)}\n')
75-
subprocess.run(cmd, shell=False)
79+
result = subprocess.run(cmd, shell=False)
80+
81+
if result.returncode != 0:
82+
exit_with_error_message('failed to compile PSYDAC kernels.')

psydac/cmd/psydac_test.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
The purpose of this module is to pyccelize all PSYDAC kernels, in the case
88
that these were modified after an editable installation of PSYDAC.
99
"""
10-
from psydac.cmd.argparse_helpers import add_help_flag, add_version_flag, exit_with_error_message
10+
from psydac.cmd.argparse_helpers import (
11+
add_help_flag,
12+
add_version_flag,
13+
exit_with_error_message,
14+
)
1115

1216
__all__ = (
1317
'setup_psydac_test_parser',
@@ -90,17 +94,17 @@ def psydac_test(*, mod, mpi, petsc, verbose, exitfirst):
9094
print(f'Removing existing Pytest cache directory: {cache_dir}\n', flush=True)
9195
shutil.rmtree(cache_dir)
9296

93-
# If no pytest.ini file exists in the current working directory, copy it
97+
# If no pytest.toml file exists in the current working directory, copy it
9498
# from the parent directory of this script (which is installed with PSYDAC)
95-
if not os.path.isfile('pytest.ini'):
99+
if not os.path.isfile('pytest.toml'):
96100
script_dir = os.path.dirname(os.path.abspath(__file__))
97101
parent_dir = os.path.dirname(script_dir)
98-
pytest_ini = os.path.join(parent_dir, 'pytest.ini')
99-
if not os.path.isfile(pytest_ini):
100-
exit_with_error_message(f'could not find pytest.ini file in {parent_dir}')
102+
pytest_cfg = os.path.join(parent_dir, 'pytest.toml')
103+
if not os.path.isfile(pytest_cfg):
104+
exit_with_error_message(f'could not find pytest.toml file in {parent_dir}')
101105
else:
102-
print(f'Copying pytest.ini from: {parent_dir}\n', flush=True)
103-
shutil.copy(pytest_ini, os.getcwd())
106+
print(f'Copying pytest.toml from: {parent_dir}\n', flush=True)
107+
shutil.copy(pytest_cfg, os.getcwd())
104108

105109
# Build the list of flags for pytest
106110
flags = []
@@ -166,4 +170,9 @@ def psydac_test(*, mod, mpi, petsc, verbose, exitfirst):
166170
time.sleep(0.1) # ensure the print is shown before subprocess output
167171

168172
# Execute the command
169-
subprocess.run(cmd, shell=False, env=os.environ)
173+
result = subprocess.run(cmd, shell=False, env=os.environ)
174+
175+
if result.returncode != 0:
176+
msg = 'the PSYDAC test suite failed. '\
177+
'Please check the output above for details.'
178+
exit_with_error_message(msg)

psydac/cmd/tests/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#---------------------------------------------------------------------------#
2+
# This file is part of PSYDAC which is released under MIT License. See the #
3+
# LICENSE file or go to https://github.com/pyccel/psydac/blob/devel/LICENSE #
4+
# for full license details. #
5+
#---------------------------------------------------------------------------#

0 commit comments

Comments
 (0)