From 144cdd870f94af2c2e62343e35b50114bd444214 Mon Sep 17 00:00:00 2001 From: relf Date: Mon, 20 Jul 2026 14:52:07 +0200 Subject: [PATCH 1/8] Move py tests out of source --- python/{egobox => }/tests/test_api.py | 0 python/{egobox => }/tests/test_egor.py | 0 python/{egobox => }/tests/test_examples.py | 2 +- python/{egobox => }/tests/test_gpmix.py | 0 python/{egobox => }/tests/test_gpx_cli.py | 4 ++-- python/{egobox => }/tests/test_mixintegor.py | 0 python/{egobox => }/tests/test_sampling.py | 0 python/{egobox => }/tests/test_sgpmix.py | 0 python/{egobox => }/tests/test_utils.py | 0 9 files changed, 3 insertions(+), 3 deletions(-) rename python/{egobox => }/tests/test_api.py (100%) rename python/{egobox => }/tests/test_egor.py (100%) rename python/{egobox => }/tests/test_examples.py (82%) rename python/{egobox => }/tests/test_gpmix.py (100%) rename python/{egobox => }/tests/test_gpx_cli.py (74%) rename python/{egobox => }/tests/test_mixintegor.py (100%) rename python/{egobox => }/tests/test_sampling.py (100%) rename python/{egobox => }/tests/test_sgpmix.py (100%) rename python/{egobox => }/tests/test_utils.py (100%) diff --git a/python/egobox/tests/test_api.py b/python/tests/test_api.py similarity index 100% rename from python/egobox/tests/test_api.py rename to python/tests/test_api.py diff --git a/python/egobox/tests/test_egor.py b/python/tests/test_egor.py similarity index 100% rename from python/egobox/tests/test_egor.py rename to python/tests/test_egor.py diff --git a/python/egobox/tests/test_examples.py b/python/tests/test_examples.py similarity index 82% rename from python/egobox/tests/test_examples.py rename to python/tests/test_examples.py index 752348c3..cb866bd7 100644 --- a/python/egobox/tests/test_examples.py +++ b/python/tests/test_examples.py @@ -3,7 +3,7 @@ from pathlib import Path -EXAMPLES_DIR = Path(__file__).resolve().parents[1] / "examples" +EXAMPLES_DIR = Path(__file__).resolve().parents[1] / "egobox" / "examples" class TestExamples(unittest.TestCase): diff --git a/python/egobox/tests/test_gpmix.py b/python/tests/test_gpmix.py similarity index 100% rename from python/egobox/tests/test_gpmix.py rename to python/tests/test_gpmix.py diff --git a/python/egobox/tests/test_gpx_cli.py b/python/tests/test_gpx_cli.py similarity index 74% rename from python/egobox/tests/test_gpx_cli.py rename to python/tests/test_gpx_cli.py index 90647e8c..36c01bdc 100644 --- a/python/egobox/tests/test_gpx_cli.py +++ b/python/tests/test_gpx_cli.py @@ -1,8 +1,8 @@ -from egobox import egobox as native +import egobox as egx def test_gpx_help_exit_code_zero(capfd): - code = native._run_gpx_cli(["--help"]) + code = egx._rust._run_gpx_cli(["--help"]) assert code == 0 out, err = capfd.readouterr() diff --git a/python/egobox/tests/test_mixintegor.py b/python/tests/test_mixintegor.py similarity index 100% rename from python/egobox/tests/test_mixintegor.py rename to python/tests/test_mixintegor.py diff --git a/python/egobox/tests/test_sampling.py b/python/tests/test_sampling.py similarity index 100% rename from python/egobox/tests/test_sampling.py rename to python/tests/test_sampling.py diff --git a/python/egobox/tests/test_sgpmix.py b/python/tests/test_sgpmix.py similarity index 100% rename from python/egobox/tests/test_sgpmix.py rename to python/tests/test_sgpmix.py diff --git a/python/egobox/tests/test_utils.py b/python/tests/test_utils.py similarity index 100% rename from python/egobox/tests/test_utils.py rename to python/tests/test_utils.py From f5bf92ab0b802b90a7f2ce446dd8505a94c876ad Mon Sep 17 00:00:00 2001 From: relf Date: Mon, 20 Jul 2026 16:53:36 +0200 Subject: [PATCH 2/8] Allow mixed python rust egobox package --- python/Cargo.toml | 2 +- python/egobox/__init__.py | 37 ++++++++++++++++++++++++++++++++++++- python/pyproject.toml | 3 ++- python/src/lib.rs | 2 +- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/python/Cargo.toml b/python/Cargo.toml index a81e4462..e2c48a43 100644 --- a/python/Cargo.toml +++ b/python/Cargo.toml @@ -11,7 +11,7 @@ readme = "README.md" publish = false [lib] -name = "egobox" +name = "_rust" crate-type = ["cdylib", "rlib"] doctest = false # do not doctest as doc uses Python style for Python API doc diff --git a/python/egobox/__init__.py b/python/egobox/__init__.py index e8e30997..6bbbaa88 100644 --- a/python/egobox/__init__.py +++ b/python/egobox/__init__.py @@ -1 +1,36 @@ -from .egobox import * # noqa +# Public API - re-export all symbols from the Rust extension +# ruff: noqa: F405 +from ._rust import * # noqa + +__all__ = [ + "ConstraintStrategy", + "CorrelationSpec", + "CstrSpec", + "Egor", + "EgorOptim", + "ExitStatus", + "FailsafeStrategy", + "FeasibleInfillStrategy", + "GpConfig", + "GpMix", + "Gpx", + "InfillOptimizer", + "InfillStrategy", + "OptimResult", + "QEiConfig", + "QEiStrategy", + "Recombination", + "RegressionSpec", + "RunInfo", + "RunStatus", + "Sampling", + "SparseGpMix", + "SparseGpx", + "SparseMethod", + "TregoConfig", + "Verbose", + "XSpec", + "XType", + "lhs", + "sampling", +] # noqa diff --git a/python/pyproject.toml b/python/pyproject.toml index 21e76379..b05a56de 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -38,7 +38,8 @@ dev = [ ] [tool.maturin] -module-name = "egobox" +python-source = "." +module-name = "egobox._rust" features = ["pyo3/extension-module"] # Optional usage of BLAS backend # cargo-extra-args = "--features linfa/intel-mkl-static" diff --git a/python/src/lib.rs b/python/src/lib.rs index fd64cfc2..19dd7d9d 100644 --- a/python/src/lib.rs +++ b/python/src/lib.rs @@ -29,7 +29,7 @@ fn _run_gpx_cli(args: Vec) -> i32 { #[doc(hidden)] #[pymodule] -fn egobox(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { +fn _rust(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { // egobox version m.add("__version__", env!("CARGO_PKG_VERSION"))?; From a5d9d718e8cb44cd6517b238689cf2bac69ec89c Mon Sep 17 00:00:00 2001 From: relf Date: Mon, 20 Jul 2026 16:54:35 +0200 Subject: [PATCH 3/8] Use rust stub generation for python API stub --- python/src/bin/stub_gen.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/python/src/bin/stub_gen.rs b/python/src/bin/stub_gen.rs index 6b8b8e0f..27dd9337 100644 --- a/python/src/bin/stub_gen.rs +++ b/python/src/bin/stub_gen.rs @@ -2,7 +2,16 @@ use pyo3_stub_gen::Result; fn main() -> Result<()> { env_logger::Builder::from_env(env_logger::Env::default().filter_or("RUST_LOG", "info")).init(); - let stub = egobox::stub_info()?; + let stub = _rust::stub_info()?; stub.generate()?; + + // The Rust stub generator generates a stub file in the python/egobox/_rust directory, + // As Python API is the same as core Rust API, we move the stub file to python/egobox/egobox.pyi + log::info!("Moving stub file to egobox/egobox.pyi"); + let from = std::path::Path::new("python/egobox/_rust/__init__.pyi"); + let to = std::path::Path::new("python/egobox/egobox.pyi"); + std::fs::rename(from, to).expect( + "Should move stub file to egobox/egobox.pyi. Ensure to run this command from the root of the repository, and that the stub file exists.", + ); Ok(()) } From 3de2a267d4bc72c4618b7dfb3664e9b0b187330c Mon Sep 17 00:00:00 2001 From: relf Date: Mon, 20 Jul 2026 17:33:25 +0200 Subject: [PATCH 4/8] Move examples dir under python dir --- .github/workflows/website.yml | 4 ++-- README.md | 2 +- python/README.md | 2 +- python/{egobox => }/examples/branin_fcstr.py | 0 .../examples/branin_hidden_constraints_efi_fe.py | 0 python/{egobox => }/examples/branin_nans.py | 0 python/{egobox => }/examples/g24.py | 0 python/{egobox => }/examples/g24_fcstr.py | 0 python/{egobox => }/examples/iooss_function.py | 0 python/{egobox => }/examples/kriging.py | 0 python/{egobox => }/examples/rastrigin.py | 0 python/{egobox => }/examples/rosenbrock_20d.py | 0 .../{egobox => }/examples/rosenbrock_2d_trego.py | 0 python/{egobox => }/examples/sampling.py | 0 website/content/examples/index.md | 14 +++++++------- website/content/reference.md | 2 +- 16 files changed, 12 insertions(+), 12 deletions(-) rename python/{egobox => }/examples/branin_fcstr.py (100%) rename python/{egobox => }/examples/branin_hidden_constraints_efi_fe.py (100%) rename python/{egobox => }/examples/branin_nans.py (100%) rename python/{egobox => }/examples/g24.py (100%) rename python/{egobox => }/examples/g24_fcstr.py (100%) rename python/{egobox => }/examples/iooss_function.py (100%) rename python/{egobox => }/examples/kriging.py (100%) rename python/{egobox => }/examples/rastrigin.py (100%) rename python/{egobox => }/examples/rosenbrock_20d.py (100%) rename python/{egobox => }/examples/rosenbrock_2d_trego.py (100%) rename python/{egobox => }/examples/sampling.py (100%) diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index 19a1a753..387c5985 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -19,8 +19,8 @@ on: - crates/gp/examples/** - website/** - notebooks/** - - python/egobox/examples/*.py - - python/egobox/tests/test_examples.py + - python/examples/*.py + - python/tests/test_examples.py workflow_dispatch: permissions: diff --git a/README.md b/README.md index f472f5af..64d96f9d 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ plt.show() See also [this example written in Rust](crates/gp/examples/kriging.rs) -See the [tutorial notebooks](https://github.com/relf/egobox/tree/master/notebooks/README.md) and [examples folder](https://github.com/relf/egobox/tree/d9db0248199558f23d966796737d7ffa8f5de589/python/egobox/examples) for more information on the usage of the optimizer and mixture of Gaussian processes surrogate model. +See the [tutorial notebooks](https://github.com/relf/egobox/tree/master/notebooks/README.md) and [examples folder](https://github.com/relf/egobox/tree/master/python/examples) for more information on the usage of the optimizer and mixture of Gaussian processes surrogate model. ## The Rust libraries diff --git a/python/README.md b/python/README.md index 2f0d3d76..021e6502 100644 --- a/python/README.md +++ b/python/README.md @@ -55,4 +55,4 @@ plt.plot(xtrain, ytrain, "o") plt.show() ``` -See the [tutorial notebooks](https://github.com/relf/egobox/tree/master/notebooks/README.md) and [examples folder](https://github.com/relf/egobox/tree/d9db0248199558f23d966796737d7ffa8f5de589/python/egobox/examples) for more information on the usage of the optimizer and mixture of Gaussian processes surrogate model. +See the [tutorial notebooks](https://github.com/relf/egobox/tree/master/notebooks/README.md) and [examples folder](https://github.com/relf/egobox/tree/master/python/examples) for more information on the usage of the optimizer and mixture of Gaussian processes surrogate model. diff --git a/python/egobox/examples/branin_fcstr.py b/python/examples/branin_fcstr.py similarity index 100% rename from python/egobox/examples/branin_fcstr.py rename to python/examples/branin_fcstr.py diff --git a/python/egobox/examples/branin_hidden_constraints_efi_fe.py b/python/examples/branin_hidden_constraints_efi_fe.py similarity index 100% rename from python/egobox/examples/branin_hidden_constraints_efi_fe.py rename to python/examples/branin_hidden_constraints_efi_fe.py diff --git a/python/egobox/examples/branin_nans.py b/python/examples/branin_nans.py similarity index 100% rename from python/egobox/examples/branin_nans.py rename to python/examples/branin_nans.py diff --git a/python/egobox/examples/g24.py b/python/examples/g24.py similarity index 100% rename from python/egobox/examples/g24.py rename to python/examples/g24.py diff --git a/python/egobox/examples/g24_fcstr.py b/python/examples/g24_fcstr.py similarity index 100% rename from python/egobox/examples/g24_fcstr.py rename to python/examples/g24_fcstr.py diff --git a/python/egobox/examples/iooss_function.py b/python/examples/iooss_function.py similarity index 100% rename from python/egobox/examples/iooss_function.py rename to python/examples/iooss_function.py diff --git a/python/egobox/examples/kriging.py b/python/examples/kriging.py similarity index 100% rename from python/egobox/examples/kriging.py rename to python/examples/kriging.py diff --git a/python/egobox/examples/rastrigin.py b/python/examples/rastrigin.py similarity index 100% rename from python/egobox/examples/rastrigin.py rename to python/examples/rastrigin.py diff --git a/python/egobox/examples/rosenbrock_20d.py b/python/examples/rosenbrock_20d.py similarity index 100% rename from python/egobox/examples/rosenbrock_20d.py rename to python/examples/rosenbrock_20d.py diff --git a/python/egobox/examples/rosenbrock_2d_trego.py b/python/examples/rosenbrock_2d_trego.py similarity index 100% rename from python/egobox/examples/rosenbrock_2d_trego.py rename to python/examples/rosenbrock_2d_trego.py diff --git a/python/egobox/examples/sampling.py b/python/examples/sampling.py similarity index 100% rename from python/egobox/examples/sampling.py rename to python/examples/sampling.py diff --git a/website/content/examples/index.md b/website/content/examples/index.md index b912ff69..2ec132e7 100644 --- a/website/content/examples/index.md +++ b/website/content/examples/index.md @@ -5,15 +5,15 @@ weight = 20 # Examples -The Python snippets below are included directly from source files under [`python/egobox/examples`](https://github.com/relf/EGObox/tree/master/python/egobox/examples/). +The Python snippets below are included directly from source files under [`python/examples`](https://github.com/relf/EGObox/tree/master/python/examples/). Here you can just copy-paste the code to run it locally, or click on the links to open the source files in a new tab. ## Optimization with _Egor_ -### Unconstrained optimization: [Rastrigin](https://github.com/relf/EGObox/blob/master/python/egobox/examples/rastrigin.py) +### Unconstrained optimization: [Rastrigin](https://github.com/relf/EGObox/blob/master/python/examples/rastrigin.py) {{ include_code( - url="https://raw.githubusercontent.com/relf/EGObox/master/python/egobox/examples/rastrigin.py", + url="https://raw.githubusercontent.com/relf/EGObox/master/python/examples/rastrigin.py", lang="python") }} @@ -27,10 +27,10 @@ Best point (x*): [ 0.00415341 -0.00058284] ![Rastrigin function optimization](img/rastrigin.png) -### Constrained optimization: [G24](https://github.com/relf/EGObox/blob/master/python/egobox/examples/g24.py) +### Constrained optimization: [G24](https://github.com/relf/EGObox/blob/master/python/examples/g24.py) {{ include_code( - url="https://raw.githubusercontent.com/relf/EGObox/master/python/egobox/examples/g24.py", + url="https://raw.githubusercontent.com/relf/EGObox/master/python/examples/g24.py", lang="python") }} @@ -40,10 +40,10 @@ Optimization f=[-5.50853583e+00 8.65985077e-04 3.83913510e-04] at [2.32948272 ## Surrogate modeling with _Gpx_ -### Simple surrogate model: [Kriging](https://github.com/relf/EGObox/blob/master/python/egobox/examples/kriging.py) +### Simple surrogate model: [Kriging](https://github.com/relf/EGObox/blob/master/python/examples/kriging.py) {{ include_code( - url="https://raw.githubusercontent.com/relf/EGObox/master/python/egobox/examples/kriging.py", + url="https://raw.githubusercontent.com/relf/EGObox/master/python/examples/kriging.py", lang="python") }} diff --git a/website/content/reference.md b/website/content/reference.md index e610a627..ef442ec3 100644 --- a/website/content/reference.md +++ b/website/content/reference.md @@ -22,5 +22,5 @@ weight = 60 - [Github repository](https://github.com/relf/EGObox) - [Notebook index](https://github.com/relf/EGObox/blob/master/notebooks/README.md) -- [Python examples directory](https://github.com/relf/EGObox/tree/master/python/egobox/examples) +- [Python examples directory](https://github.com/relf/EGObox/tree/master/python/examples) - [Rust crate directory](https://github.com/relf/EGObox/tree/master/crates) From f8f77413c09787ee17a2da23af4bd8b45eb012e0 Mon Sep 17 00:00:00 2001 From: relf Date: Mon, 20 Jul 2026 17:56:42 +0200 Subject: [PATCH 5/8] Fix examples tests --- python/examples/kriging.py | 4 ++++ python/examples/rastrigin.py | 4 ++++ python/tests/test_examples.py | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/python/examples/kriging.py b/python/examples/kriging.py index 616e8b60..5c0909bb 100644 --- a/python/examples/kriging.py +++ b/python/examples/kriging.py @@ -4,6 +4,10 @@ import numpy as np import matplotlib.pyplot as plt +import warnings + +warnings.filterwarnings("ignore", category=UserWarning) + # Comment out the following line to display the plot in a window matplotlib.use("Agg") diff --git a/python/examples/rastrigin.py b/python/examples/rastrigin.py index cc3e951f..2f202d66 100644 --- a/python/examples/rastrigin.py +++ b/python/examples/rastrigin.py @@ -9,6 +9,10 @@ import egobox as egx import matplotlib.pyplot as plt +import warnings + +warnings.filterwarnings("ignore", category=UserWarning) + # Comment out the following line to display the plot in a window matplotlib.use("Agg") diff --git a/python/tests/test_examples.py b/python/tests/test_examples.py index cb866bd7..752348c3 100644 --- a/python/tests/test_examples.py +++ b/python/tests/test_examples.py @@ -3,7 +3,7 @@ from pathlib import Path -EXAMPLES_DIR = Path(__file__).resolve().parents[1] / "egobox" / "examples" +EXAMPLES_DIR = Path(__file__).resolve().parents[1] / "examples" class TestExamples(unittest.TestCase): From f38d6c7fbe88c678a2af4ebef1bf0a281c0e8bad Mon Sep 17 00:00:00 2001 From: relf Date: Mon, 20 Jul 2026 18:05:55 +0200 Subject: [PATCH 6/8] Linting --- python/examples/kriging.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/python/examples/kriging.py b/python/examples/kriging.py index 5c0909bb..8b086e1f 100644 --- a/python/examples/kriging.py +++ b/python/examples/kriging.py @@ -3,7 +3,7 @@ import matplotlib import numpy as np import matplotlib.pyplot as plt - +import egobox as egx import warnings warnings.filterwarnings("ignore", category=UserWarning) @@ -11,7 +11,6 @@ # Comment out the following line to display the plot in a window matplotlib.use("Agg") -import egobox as egx xt = np.array([[0.0, 1.0, 1.5, 2.0, 3.0, 4.0]]).T yt = np.array([[0.0, 1.0, 1.7, 1.5, 0.9, 1.0]]).T From f24d88a2aa342b75678acaa5c3848db9422702a1 Mon Sep 17 00:00:00 2001 From: relf Date: Mon, 20 Jul 2026 18:13:05 +0200 Subject: [PATCH 7/8] Fix test path --- .github/workflows/website.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index 387c5985..e7eaf527 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -80,7 +80,7 @@ jobs: - name: Verify website examples working-directory: python - run: uv run pytest egobox/tests/test_examples.py + run: uv run pytest tests/test_examples.py - name: Install Zola uses: taiki-e/install-action@v2 From b869202282a854aac0d28f3c26499fb40c783966 Mon Sep 17 00:00:00 2001 From: relf Date: Mon, 20 Jul 2026 18:20:12 +0200 Subject: [PATCH 8/8] pytest on tests dir --- .github/workflows/pytest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index fa2cb6ef..2e57b337 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -68,6 +68,6 @@ jobs: - name: Test Python working-directory: python run: | - uv run pytest + uv run pytest tests shell: bash