From 7bc954c3c554d5bc111bda08e3b63f73234b73ac Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Sat, 28 Dec 2024 18:30:51 +0100 Subject: [PATCH 1/5] Eradicate wait_on_error --- codepy/cuda.py | 2 +- codepy/jit.py | 23 ++++++----------------- test/test_identical_symbols.py | 7 +------ 3 files changed, 8 insertions(+), 24 deletions(-) diff --git a/codepy/cuda.py b/codepy/cuda.py index 61302bd..33b09c9 100644 --- a/codepy/cuda.py +++ b/codepy/cuda.py @@ -101,7 +101,7 @@ def compile(self, object=True, **local_host_kwargs) device_checksum, _device_mod_name, device_object, device_compiled = \ compile_from_string( - nvcc_toolchain, "gpu", device_code, "gpu.cu", + nvcc_toolchain, "gpu", device_code, source_name="gpu.cu", object=True, **local_nvcc_kwargs) # The name of the shared lib depends on the hex checksums of both # host and device code to prevent accidentally returned a cached diff --git a/codepy/jit.py b/codepy/jit.py index 77e9b5c..45118a7 100644 --- a/codepy/jit.py +++ b/codepy/jit.py @@ -32,7 +32,6 @@ from types import ModuleType from typing import Any, NamedTuple -from codepy import CompileError from codepy.toolchain import GCCLikeToolchain, Toolchain @@ -195,7 +194,6 @@ def extension_from_string( source_name: str | list[str] = "module.cpp", cache_dir: str | None = None, debug: bool = False, - wait_on_error: bool | None = None, debug_recompile: bool = True, sleep_delay: int = 1) -> ModuleType: """Return a reference to the extension module *name*, which can be built @@ -221,8 +219,9 @@ def extension_from_string( recompilation is taking place. """ _checksum, mod_name, ext_file, _recompiled = ( - compile_from_string(toolchain, name, source_string, source_name, - cache_dir, debug, wait_on_error, debug_recompile, + compile_from_string(toolchain, name, source_string, source_name=source_name, + cache_dir=cache_dir, debug=debug, + debug_recompile=debug_recompile, object=False, sleep_delay=sleep_delay)) # try loading it @@ -250,10 +249,10 @@ def compile_from_string( toolchain: Toolchain, name: str, source_string: str | bytes | list[str] | list[bytes], + *, source_name: str | list[str] | None = None, cache_dir: str | None = None, debug: bool = False, - wait_on_error: bool | None = None, debug_recompile: bool = True, object: bool = False, source_is_binary: bool = False, @@ -306,11 +305,6 @@ def compile_from_string( if isinstance(source_name, str): source_name = [source_name] - if wait_on_error is not None: - from warnings import warn - warn("Passing 'wait_on_error' is deprecated and has no effect. ", - DeprecationWarning, stacklevel=2) - import os if cache_dir is None: @@ -487,7 +481,7 @@ def link_extension( mod_name: str, cache_dir: str | None = None, debug: bool = False, - wait_on_error: bool = True) -> ModuleType: + ) -> ModuleType: if not isinstance(toolchain, GCCLikeToolchain): raise TypeError(f"Unsupported toolchain type: {type(toolchain)}") @@ -501,12 +495,7 @@ def link_extension( destination_base, mod_name + toolchain.so_ext) - try: - toolchain.link_extension(destination, objects, debug=debug) - except CompileError: - if wait_on_error: - input(f"Link error, examine {objects}, then press [Enter]") - raise + toolchain.link_extension(destination, objects, debug=debug) # try loading it from codepy.tools import load_dynamic diff --git a/test/test_identical_symbols.py b/test/test_identical_symbols.py index a6b0eee..9b1669b 100644 --- a/test/test_identical_symbols.py +++ b/test/test_identical_symbols.py @@ -1,7 +1,5 @@ from types import ModuleType -import pytest - def make_greet_mod(greeting: str) -> ModuleType: from cgen import ( @@ -25,12 +23,9 @@ def make_greet_mod(greeting: str) -> ModuleType: )) from codepy.toolchain import guess_toolchain - return mod.compile(guess_toolchain(), wait_on_error=True) + return mod.compile(guess_toolchain()) -@pytest.mark.xfail(reason="You probably don't have " - "Boost.Python installed where I am looking for it, " - "and that's OK.") def test_identical_symbols() -> None: us = make_greet_mod("Hi there") aussie = make_greet_mod("G'day") From 1c434fb59058c81d5b02c413d62258102c60b551 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Tue, 4 Feb 2025 18:06:42 -0600 Subject: [PATCH 2/5] Github CI: Install Boost Python --- .github/workflows/ci.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0c6fdd2..6ee79b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,12 +33,28 @@ jobs: uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} + - uses: MarkusJx/install-boost@v2 + with: + boost_version: 1.87.0 + boost_install_dir: /home/runner/boost + id: install-boost - name: "Main Script" + env: + BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} run: | curl -L -O https://tiker.net/ci-support-v0 . ./ci-support-v0 + PY_VER=$(python3 -c 'import sys; print(f"{sys.version_info[0]}{sys.version_info[1]}")') + cat > $HOME/.aksetup-defaults.py < Date: Wed, 5 Feb 2025 12:38:13 -0600 Subject: [PATCH 3/5] Github CI: Limit concurrency --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6ee79b7..4e1e3e5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,6 +9,10 @@ on: schedule: - cron: '17 3 * * 0' +concurrency: + group: ${{ github.head_ref || github.ref_name }} + cancel-in-progress: true + jobs: ruff: name: Ruff From 624b9aebc627991f248e0e983d3d4c4ae5f9184d Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Wed, 5 Feb 2025 12:54:54 -0600 Subject: [PATCH 4/5] Move module docs into module docstrings --- codepy/__init__.py | 12 ++++++++++++ codepy/bpl.py | 9 ++++++++- codepy/jit.py | 14 ++++++++++---- codepy/toolchain.py | 22 ++++++++++++++++++++-- doc/index.rst | 2 -- doc/jit.rst | 41 +---------------------------------------- 6 files changed, 51 insertions(+), 49 deletions(-) diff --git a/codepy/__init__.py b/codepy/__init__.py index 1cd9d88..d99a663 100644 --- a/codepy/__init__.py +++ b/codepy/__init__.py @@ -1,2 +1,14 @@ +""" +Errors +^^^^^^ + +.. autoexception:: CompileError + +.. automodule:: codepy.jit +.. automodule:: codepy.toolchain +.. automodule:: codepy.bpl +""" + + class CompileError(Exception): pass diff --git a/codepy/bpl.py b/codepy/bpl.py index f6f7455..4c3c4d6 100644 --- a/codepy/bpl.py +++ b/codepy/bpl.py @@ -1,4 +1,11 @@ -"""Convenience interface for using CodePy with Boost.Python.""" +""" +:mod:`codepy.bpl` -- Support for Boost.Python +--------------------------------------------- + +.. autoclass:: BoostPythonModule + :members: + :undoc-members: +""" from collections.abc import Callable, Iterable from dataclasses import replace diff --git a/codepy/jit.py b/codepy/jit.py index 45118a7..8aea1af 100644 --- a/codepy/jit.py +++ b/codepy/jit.py @@ -1,4 +1,10 @@ -"""Just-in-time Python extension compilation.""" +""" +:mod:`codepy.jit` -- Compilation and Linking of C Source Code +------------------------------------------------------------- + +.. autofunction:: extension_file_from_string +.. autofunction:: extension_from_string +""" __copyright__ = """ @@ -56,7 +62,7 @@ def extension_file_from_string( debug: bool = False) -> None: """Using *toolchain*, build the extension file named *ext_file* from the source code in *source_string*, which is saved to a - temporary file named *source_name*. Raise :exc:`CompileError` in + temporary file named *source_name*. Raise :exc:`~codepy.CompileError` in case of error. If *debug* is True, show commands involved in the build. @@ -198,7 +204,7 @@ def extension_from_string( sleep_delay: int = 1) -> ModuleType: """Return a reference to the extension module *name*, which can be built from the source code in *source_string* if necessary. Raise - :exc:`CompileError` in case of error. + :exc:`codepy.CompileError` in case of error. Compiled code is cached in *cache_dir* and available immediately if it has been compiled at some point in the past. Compiler and Python API versions @@ -264,7 +270,7 @@ def compile_from_string( *recompiled* is *True* if the object had to be recompiled, *False* if the cache is hit. - Raises :exc:`CompileError` in case of error. The *mod_name* and *file_name* + Raises :exc:`~codepy.CompileError` in case of error. The *mod_name* and *file_name* are designed to be used with ``load_dynamic`` to load a Python module from this object, if desired. diff --git a/codepy/toolchain.py b/codepy/toolchain.py index c11370a..29aafb3 100644 --- a/codepy/toolchain.py +++ b/codepy/toolchain.py @@ -1,4 +1,22 @@ -"""Toolchains for Just-in-time Python extension compilation.""" +""" +:mod:`codepy.toolchain` -- Tool support code +-------------------------------------------- + +.. autoexception:: ToolchainGuessError + +.. autoclass:: Toolchain + :members: copy, get_version, abi_id, add_library, build_extension + :undoc-members: + +.. autoclass:: GCCLikeToolchain + :show-inheritance: + +.. autoclass:: GCCToolchain + :show-inheritance: + +.. autofunction:: guess_toolchain + +""" __copyright__ = """ "Copyright (C) 2008,9 Andreas Kloeckner, Bryan Catanzaro @@ -108,7 +126,7 @@ def build_extension(self, source_files: list[str], debug: bool = False) -> None: """Create the extension file *ext_file* from *source_files* - by invoking the toolchain. Raise :exc:`~codepy.jit.CompileError` in + by invoking the toolchain. Raise :exc:`~codepy.CompileError` in case of error. If *debug* is True, print the commands executed. diff --git a/doc/index.rst b/doc/index.rst index 1c522cc..8c398ce 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -5,8 +5,6 @@ Welcome to CodePy's documentation! ================================== -.. module:: codepy - CodePy is a C metaprogramming toolkit for Python. It handles two aspects of metaprogramming: diff --git a/doc/jit.rst b/doc/jit.rst index 2de0f85..053d5a9 100644 --- a/doc/jit.rst +++ b/doc/jit.rst @@ -14,43 +14,4 @@ to determine a few configuration values, notably: For lack of better installation documentation at this moment, please see `this wiki page `_. -:mod:`codepy.jit` -- Compilation and Linking of C Source Code -------------------------------------------------------------- - -.. module:: codepy.jit - -.. autofunction:: extension_file_from_string -.. autofunction:: extension_from_string - -Errors -^^^^^^ - -.. autoexception:: CompileError - -:mod:`codepy.toolchain` -- Tool support code --------------------------------------------- - -.. module:: codepy.toolchain - -.. autoexception:: ToolchainGuessError - -.. autoclass:: Toolchain - :members: copy, get_version, abi_id, add_library, build_extension - :undoc-members: - -.. autoclass:: GCCLikeToolchain - :show-inheritance: - -.. autoclass:: GCCToolchain - :show-inheritance: - -.. autofunction:: guess_toolchain - -:mod:`codepy.bpl` -- Support for Boost.Python ---------------------------------------------- - -.. automodule:: codepy.bpl - -.. autoclass:: BoostPythonModule - :members: - :undoc-members: +.. automodule:: codepy From 961e8a4c5bdce5999c0831b4e3db40f6f8caadf7 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Wed, 5 Feb 2025 13:17:00 -0600 Subject: [PATCH 5/5] Fix Boost.Python libname finding --- codepy/libraries.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/codepy/libraries.py b/codepy/libraries.py index b8f1176..42364b5 100644 --- a/codepy/libraries.py +++ b/codepy/libraries.py @@ -117,7 +117,12 @@ def update_config(fname: str) -> None: def get_boost_libname(basename: str, aksetup: Config) -> list[str]: varname = f"BOOST_{basename.upper()}_LIBNAME" - libs = getlist(aksetup, varname, [f"boost_{basename}"]) + default = f"boost_{basename}" + if basename == "python": + import sys + version = sys.version_info[:2] + default = "boost_python{}{}".format(*version) + libs = getlist(aksetup, varname, [default]) return libs @@ -133,7 +138,7 @@ def add_boost_python(toolchain: Toolchain) -> None: getlist(aksetup, "BOOST_INC_DIR", []), getlist(aksetup, "BOOST_LIB_DIR", []), [ - *get_boost_libname("python{}{}".format(*version), aksetup), + *get_boost_libname("python", aksetup), "python{}.{}{}".format(*version, sys.abiflags), ])