Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/ci-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,9 @@ dependencies: |
dependency_branch: develop

parallelism_factor: 8

python_requirements: libs/pyext/test/requirements-test.txt

overrides:
rocky-8.6:
python_version: "3.11"
13 changes: 13 additions & 0 deletions .github/ci-hpc-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ build:
- -DENABLE_ALL_TESTS=ON
ctest_options:
- -L nightly
requirements: libs/pyext/test/requirements-test.txt

gnu-15.2.0:
build:
Expand All @@ -37,10 +38,12 @@ gnu-15.2.0:
-DPython3_LIBRARIES=/usr/local/apps/python3/3.13.13-01/lib64/libpython3.13.so
-DPython3_LIBRARY_DIRS=/usr/local/apps/python3/3.13.13-01/lib64
-DCMAKE_PREFIX_PATH=/usr/local/apps/python3/3.13.13-01/lib/python3.13/site-packages/pybind11/share/cmake/pybind11
-DECFLOW_PYEXT_TEST_LD_LIBRARY_PATH=/usr/local/apps/gcc/15.2.0/lib64
# Note: Python 3.13.13-01, provides Pybind11 3.0.4.
ctest_options:
# disable s_http* tests
- -L nightly -E '(s_http)'
requirements: libs/pyext/test/requirements-test.txt

gnu-14.2.0:
build:
Expand All @@ -65,6 +68,7 @@ gnu-14.2.0:
-DPython3_LIBRARIES=/usr/local/apps/python3/3.12.9-01/lib64/libpython3.12.so
-DPython3_LIBRARY_DIRS=/usr/local/apps/python3/3.12.9-01/lib64
-DCMAKE_PREFIX_PATH=/usr/local/apps/python3/3.13.13-01/lib/python3.13/site-packages/pybind11/share/cmake/pybind11
-DECFLOW_PYEXT_TEST_LD_LIBRARY_PATH=/usr/local/apps/gcc/14.2.0/lib64
# Note: Python 3.13.13-01, provides Pybind11 3.0.4.
#
# Important:
Expand All @@ -73,6 +77,7 @@ gnu-14.2.0:
ctest_options:
# disable s_http* tests
- -L nightly -E '(s_http)'
requirements: libs/pyext/test/requirements-test.txt

gnu-12.2.0:
build:
Expand Down Expand Up @@ -101,6 +106,7 @@ gnu-12.2.0:
ctest_options:
# disable s_http* tests
- -L nightly -E '(s_http)'
requirements: libs/pyext/test/requirements-test.txt

gnu-8.5.0:
build:
Expand Down Expand Up @@ -129,6 +135,7 @@ gnu-8.5.0:
ctest_options:
# disable s_http* tests
- -L nightly -E '(s_http)'
requirements: libs/pyext/test/requirements-test.txt

intel-2025.3.1:
build:
Expand Down Expand Up @@ -159,6 +166,7 @@ intel-2025.3.1:
ctest_options:
# disable s_http* tests
- -L nightly -E '(s_http)'
requirements: libs/pyext/test/requirements-test.txt

intel-2025.0.1:
build:
Expand Down Expand Up @@ -192,6 +200,7 @@ intel-2025.0.1:
ctest_options:
# disable s_http* tests
- -L nightly -E '(s_http)'
requirements: libs/pyext/test/requirements-test.txt

intel-2021.4.0:
build:
Expand Down Expand Up @@ -220,6 +229,7 @@ intel-2021.4.0:
# Note: Python 3.10.10-01, provides Pybind11 2.10.3.
ctest_options:
- -L nightly -E '(py3_|s_http)'
requirements: libs/pyext/test/requirements-test.txt

nvidia-24.11:
build:
Expand Down Expand Up @@ -252,6 +262,7 @@ nvidia-24.11:
ctest_options:
# disable all tests
- --version
requirements: libs/pyext/test/requirements-test.txt

nvidia-22.11:
build:
Expand Down Expand Up @@ -280,6 +291,7 @@ nvidia-22.11:
ctest_options:
# disable all tests
- --version
requirements: libs/pyext/test/requirements-test.txt

aocc-4.0.0:
build:
Expand Down Expand Up @@ -308,3 +320,4 @@ aocc-4.0.0:
ctest_options:
# disable all tests
- --version
requirements: libs/pyext/test/requirements-test.txt
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
downstream-ci:
name: downstream-ci
if: ${{ !github.event.pull_request.head.repo.fork && github.event.action != 'labeled' || github.event.label.name == 'approved-for-ci' }}
uses: ecmwf/downstream-ci/.github/workflows/downstream-ci.yml@main
uses: ecmwf/downstream-ci/.github/workflows/downstream-ci.yml@test-ecflow-py
with:
ecflow: ecmwf/ecflow@${{ github.event.pull_request.head.sha || github.sha }}
skip_matrix_jobs: |
Expand All @@ -49,7 +49,7 @@ jobs:
downstream-ci-hpc:
name: downstream-ci-hpc
if: ${{ !github.event.pull_request.head.repo.fork && github.event.action != 'labeled' || github.event.label.name == 'approved-for-ci' }}
uses: ecmwf/downstream-ci/.github/workflows/downstream-ci-hpc.yml@main
uses: ecmwf/downstream-ci/.github/workflows/downstream-ci-hpc.yml@test-ecflow-py
with:
ecflow: ecmwf/ecflow@${{ github.event.pull_request.head.sha || github.sha }}
skip_matrix_jobs: |
Expand Down
55 changes: 51 additions & 4 deletions libs/pyext/python3/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,48 @@ set_target_properties(ecflow3
# =====================================================================
# tests

# The python tests are executed via 'python -m pytest' (see below), so
# pytest must be available for the selected interpreter. Detect it at configure
# time and warn early, rather than having every py3_u_* / py3_s_* test fail at run time
# with 'No module named pytest'.
execute_process(
COMMAND ${Python3_EXECUTABLE} -c "import pytest"
RESULT_VARIABLE _ECFLOW_HAVE_PYTEST
OUTPUT_QUIET ERROR_QUIET)
if( NOT _ECFLOW_HAVE_PYTEST EQUAL 0 )
message( WARNING
"pytest was not found for ${Python3_EXECUTABLE}; the python tests "
"(py3_u_* and py3_s_*) will fail to run. Install it with:\n"
" ${Python3_EXECUTABLE} -m pip install -r "
"${CMAKE_CURRENT_SOURCE_DIR}/../test/requirements-test.txt" )
endif()

#
# When using some HPC toolchains, the dynamic linker for ecflow resolves and loads the platform default libstdc++ first,
# instead of the one that ecflow.so was built against. This leads to symbol version mismatches, and the python tests
# fail with errors like:
#
# /lib64/libstdc++.so.6: error: version lookup error: version `GLIBCXX_3.4.32' not found
# (required by /path/to/ecflow/build/libs/pyext/python3/ecflow.so) (fatal)
#
# ECFLOW_PYEXT_TEST_LD_LIBRARY_PATH allows a runtime library directory to be prepended to LD_LIBRARY_PATH, so that
# the correct libstdc++.so.6 is used by the python tests.
#
set(ECFLOW_PYEXT_TEST_LD_LIBRARY_PATH "" CACHE STRING
"Colon-separated directories prepended to LD_LIBRARY_PATH when running the python tests")

set( _ECFLOW_PYEXT_ENVIRONMENT
"PATH=${Python3_EXECUTABLE_DIR}:$ENV{PATH}"
"PYTHONPATH=${ECFLOW_PYTHONPATH}"
)
if( ECFLOW_PYEXT_TEST_LD_LIBRARY_PATH )
if( DEFINED ENV{LD_LIBRARY_PATH} AND NOT "$ENV{LD_LIBRARY_PATH}" STREQUAL "" )
list( APPEND _ECFLOW_PYEXT_ENVIRONMENT "LD_LIBRARY_PATH=${ECFLOW_PYEXT_TEST_LD_LIBRARY_PATH}:$ENV{LD_LIBRARY_PATH}" )
else()
list( APPEND _ECFLOW_PYEXT_ENVIRONMENT "LD_LIBRARY_PATH=${ECFLOW_PYEXT_TEST_LD_LIBRARY_PATH}" )
endif()
endif()

foreach( test ${u_tests} )
ecbuild_add_test(
TARGET
Expand All @@ -70,9 +112,9 @@ foreach( test ${u_tests} )
unit python nightly fast
TYPE PYTHON
ARGS
${CMAKE_CURRENT_SOURCE_DIR}/../test/py_${test}.py
-m pytest ${CMAKE_CURRENT_SOURCE_DIR}/../test/py_${test}.py -v
ENVIRONMENT
"PATH=${Python3_EXECUTABLE_DIR}:$ENV{PATH};PYTHONPATH=${ECFLOW_PYTHONPATH}"
${_ECFLOW_PYEXT_ENVIRONMENT}
TEST_DEPENDS
u_base
)
Expand All @@ -81,6 +123,11 @@ endforeach()

if ( ENABLE_ALL_TESTS AND ENABLE_SERVER)

#
# Python integration tests run the ecflow server, and thus use ECF_SSL_DIR to find the generated SSL certificates.
#
list( APPEND _ECFLOW_PYEXT_ENVIRONMENT "ECF_SSL_DIR=${CMAKE_CURRENT_BINARY_DIR}/" )

foreach( test ${s_tests} )
ecbuild_add_test(
TARGET
Expand All @@ -89,9 +136,9 @@ if ( ENABLE_ALL_TESTS AND ENABLE_SERVER)
integration python nightly slow
TYPE PYTHON
ARGS
${CMAKE_CURRENT_SOURCE_DIR}/../test/py_${test}.py
-m pytest ${CMAKE_CURRENT_SOURCE_DIR}/../test/py_${test}.py -v
ENVIRONMENT
"PATH=${Python3_EXECUTABLE_DIR}:$ENV{PATH};PYTHONPATH=${ECFLOW_PYTHONPATH};ECF_SSL_DIR=${CMAKE_CURRENT_BINARY_DIR}/"
${_ECFLOW_PYEXT_ENVIRONMENT}
TEST_DEPENDS
u_base
)
Expand Down
29 changes: 29 additions & 0 deletions libs/pyext/test/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#
# Copyright 2009- ECMWF.
#
# This software is licensed under the terms of the Apache Licence version 2.0
# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
# In applying this licence, ECMWF does not waive the privileges and immunities
# granted to it by virtue of its status as an intergovernmental organisation
# nor does it submit to any jurisdiction.
#

"""
Shared pytest configuration for the ecFlow Python binding tests.

This file is intentionally minimal. Most unit tests only need a working
``import ecflow`` and use bare ``assert`` statements. Global fixtures or
hooks should only be added here when they are genuinely shared across many
files.
"""

import pytest # to ensure pytest is available

def pytest_configure(config):
"""Ensure ecflow is importable before any test is collected."""
try:
import ecflow # noqa: F401
except ImportError as exc:
raise RuntimeError(
"Could not import ecflow. Make sure the binding is on PYTHONPATH."
) from exc
Loading
Loading