diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 90fe1a2..cd11833 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,12 +19,14 @@ jobs: strategy: fail-fast: false # Mirrors CppInterOp's cppyy PR cells: clang-repl on the same OS/arch/LLVM - # /valgrind combos at Python 3.14, plus a cling cell. Breadth (3.12/3.13, - # C++17, LLVM 20, arm) lives in nightly. + # /valgrind combos at Python 3.14, plus a cling cell and a C++23 cell + # (test_cpp23features runs only there). Breadth (3.12/3.13, C++17, LLVM + # 20, arm) lives in nightly. matrix: include: - { os: ubuntu-24.04, llvm: '21', flavor: system, py: '3.14', cxx: '20', vg: true } - { os: ubuntu-24.04, llvm: '22', flavor: '', py: '3.14', cxx: '20' } + - { os: ubuntu-24.04, llvm: '22', flavor: '', py: '3.14', cxx: '23' } - { os: macos-26, llvm: '21', flavor: system, py: '3.14', cxx: '20' } - { os: macos-26-intel, llvm: '21', flavor: system, py: '3.14', cxx: '20' } # cling backend, against the cached llvm-root (cling-llvm22) recipe cell. diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 88d40d6..a452156 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -25,12 +25,13 @@ jobs: strategy: fail-fast: false matrix: - # Superset of the PR matrix + breadth (py 3.12/3.13, C++17, LLVM 20, arm) - # and one cling cell. valgrind only where a supp is vendored: the LLVM 21 - # cells (clang21) and the arm LLVM 22 cell (clang22), both under + # Superset of the PR matrix + breadth (py 3.12/3.13, C++17/23, LLVM 20, + # arm) and one cling cell. valgrind only where a supp is vendored: the + # LLVM 21 cells (clang21) and the arm LLVM 22 cell (clang22), both under # .github/valgrind/. include: - { os: ubuntu-24.04, llvm: '20', flavor: system, py: '3.12', cxx: '17' } + - { os: ubuntu-24.04, llvm: '22', flavor: '', py: '3.14', cxx: '23' } - { os: ubuntu-24.04, llvm: '21', flavor: system, py: '3.13', cxx: '20', vg: true } - { os: ubuntu-24.04, llvm: '21', flavor: system, py: '3.14', cxx: '20', vg: true } - { os: ubuntu-24.04, llvm: '22', flavor: '', py: '3.14', cxx: '20' } @@ -38,6 +39,7 @@ jobs: - { os: ubuntu-24.04-arm, llvm: '22', flavor: '', py: '3.13', cxx: '20', vg: true } - { os: ubuntu-24.04-arm, llvm: '20', flavor: system, py: '3.12', cxx: '17' } - { os: macos-26, llvm: '21', flavor: system, py: '3.12', cxx: '20' } + - { os: macos-26, llvm: '21', flavor: system, py: '3.14', cxx: '23' } - { os: macos-26-intel, llvm: '21', flavor: system, py: '3.12', cxx: '20' } # cling backend, against the cached llvm-root (cling-llvm22) recipe cell. - { os: ubuntu-24.04, llvm: '22', flavor: cling, flavor_version: cling-llvm22, py: '3.13', cxx: '20' } diff --git a/test/support.py b/test/support.py index 34b9f9a..5d1e74e 100644 --- a/test/support.py +++ b/test/support.py @@ -94,4 +94,12 @@ def setup_make(targetname): == 1 ) IS_CLING = not IS_CLANG_REPL +IS_CPP23 = ( + cppjit.evaluate("""#if __cplusplus >= 202302L + true + #else + false + #endif\n""") + == 1 +) IS_VALGRIND = True if os.getenv("IS_VALGRIND") else False diff --git a/test/test_cpp23features.py b/test/test_cpp23features.py index 0d2925a..16b5423 100644 --- a/test/test_cpp23features.py +++ b/test/test_cpp23features.py @@ -1,39 +1,23 @@ -import os -import subprocess -import sys - from pytest import mark +from support import IS_CPP23 -# C++23 isn't the stack's default and the interpreter is a process-wide -# singleton pinned at the first `import cppjit`. So TestCPP23Driver re-runs the -# whole class once in a child process that selects C++23 before import -# (EXTRA_CLING_ARGS for cling, CPPINTEROP_EXTRA_INTERPRETER_ARGS for clang-repl); -# all tests then share that one interpreter. To iterate locally, run the tests -# directly in "child mode": +# The interpreter is a process-wide singleton whose C++ standard is pinned at +# the first `import cppjit`, so these tests only run when the suite itself is +# under C++23 (the cxx-standard=23 CI cells). To run them locally (the env var +# reaches CreateInterpreter for both clang-repl and cling): # -# CPPJIT_TEST_CPP23_CHILD=1 EXTRA_CLING_ARGS=-std=c++23 \ -# CPPINTEROP_EXTRA_INTERPRETER_ARGS=-std=c++23 \ -# pytest -v test_cpp23features.py - -_CPP23_CHILD = "CPPJIT_TEST_CPP23_CHILD" -_IN_CHILD = bool(os.environ.get(_CPP23_CHILD)) +# CPPINTEROP_EXTRA_INTERPRETER_ARGS=-std=c++23 pytest -v test_cpp23features.py @mark.skipif( - not _IN_CHILD, - reason="C++23 tests run in the child interpreter launched by TestCPP23Driver", + not IS_CPP23, + reason="C++23 tests need the interpreter to run under -std=c++23", ) class TestCPP23FEATURES: - """C++23 features driven via cppjit.cppdef through the JIT (clang-repl/cling). - - The class owns one C++23 interpreter (booted in setup_class); tests share - it via ``self.cppjit``. - """ + """C++23 features driven via cppjit.cppdef through the JIT (clang-repl/cling).""" @classmethod def setup_class(cls): - # In the child process C++23 is already selected, so this one-time boot - # is the C++23 interpreter every test shares. import cppjit cls.cppjit = cppjit @@ -442,33 +426,3 @@ def test21_blog_sfinae_friendly_transform(self): """) assert cppjit.gbl.Cpp23DeducingThis.drive_transform() == 42 - - -@mark.skipif(_IN_CHILD, reason="launcher runs only in the parent process") -class TestCPP23Driver: - """Re-run TestCPP23FEATURES once in a child interpreter pinned to C++23.""" - - def test_run_under_cpp23(self): - env = dict(os.environ) - env[_CPP23_CHILD] = "1" - env["EXTRA_CLING_ARGS"] = "-std=c++23" # cling - env["CPPINTEROP_EXTRA_INTERPRETER_ARGS"] = "-std=c++23" # clang-repl - proc = subprocess.run( - [ - sys.executable, - "-m", - "pytest", - "-q", - "-p", - "no:cacheprovider", - os.path.basename(__file__), - ], - cwd=os.path.dirname(os.path.abspath(__file__)), - env=env, - capture_output=True, - text=True, - ) - assert proc.returncode == 0, ( - "C++23 child run failed (rc=%d)\n--- stdout ---\n%s\n--- stderr ---\n%s" - % (proc.returncode, proc.stdout, proc.stderr) - ) diff --git a/test/test_datatypes.py b/test/test_datatypes.py index eed3b3a..89df961 100644 --- a/test/test_datatypes.py +++ b/test/test_datatypes.py @@ -2,7 +2,7 @@ import py from pytest import mark, raises, skip -from support import IS_CLANG_REPL, IS_MAC, pylong, pyunicode, setup_make +from support import IS_CLANG_REPL, IS_CPP23, IS_MAC, pylong, pyunicode, setup_make currpath = py.path.local(__file__).dirpath() test_dct = str(currpath.join("cpp/datatypesDict")) @@ -20,6 +20,12 @@ def setup_class(cls): cls.datatypes = cppjit.load_reflection_info(cls.test_dct) cls.N = 5 # cppjit.gbl.N + @mark.xfail( + condition=IS_CPP23, + reason="since C++23 (P1467) the narrowing std::complex to " + "complex constructor is explicit, breaking the implicit " + "conversion of Python complex arguments", + ) def test01_instance_data_read_access(self): """Read access to instance public data and verify values"""