diff --git a/pkgs/by-name/ab/abseil-cpp_202505/package.nix b/pkgs/by-name/ab/abseil-cpp_202505/package.nix new file mode 100644 index 000000000000..c1884d4a953d --- /dev/null +++ b/pkgs/by-name/ab/abseil-cpp_202505/package.nix @@ -0,0 +1,45 @@ +{ + lib, + stdenv, + fetchFromGitHub, + cmake, + gtest, + static ? stdenv.hostPlatform.isStatic, + cxxStandard ? null, +}: + +stdenv.mkDerivation (finalAttrs: { + pname = "abseil-cpp"; + version = "20250512.1"; + + src = fetchFromGitHub { + owner = "abseil"; + repo = "abseil-cpp"; + tag = finalAttrs.version; + hash = "sha256-eB7OqTO9Vwts9nYQ/Mdq0Ds4T1KgmmpYdzU09VPWOhk="; + }; + + cmakeFlags = [ + (lib.cmakeBool "ABSL_BUILD_TEST_HELPERS" true) + (lib.cmakeBool "ABSL_USE_EXTERNAL_GOOGLETEST" true) + (lib.cmakeBool "BUILD_SHARED_LIBS" (!static)) + ] + ++ lib.optionals (cxxStandard != null) [ + (lib.cmakeFeature "CMAKE_CXX_STANDARD" cxxStandard) + ]; + + strictDeps = true; + + nativeBuildInputs = [ cmake ]; + + buildInputs = [ gtest ]; + + meta = { + description = "Open-source collection of C++ code designed to augment the C++ standard library"; + homepage = "https://abseil.io/"; + changelog = "https://github.com/abseil/abseil-cpp/releases/tag/${finalAttrs.version}"; + license = lib.licenses.asl20; + platforms = lib.platforms.all; + maintainers = [ lib.maintainers.GaetanLepage ]; + }; +}) diff --git a/pkgs/by-name/or/or-tools/0001-Do-not-try-to-copy-pybind11_abseil-status-extension-.patch b/pkgs/by-name/or/or-tools/0001-Do-not-try-to-copy-pybind11_abseil-status-extension-.patch index b3529481eb8e..519c775ad4af 100644 --- a/pkgs/by-name/or/or-tools/0001-Do-not-try-to-copy-pybind11_abseil-status-extension-.patch +++ b/pkgs/by-name/or/or-tools/0001-Do-not-try-to-copy-pybind11_abseil-status-extension-.patch @@ -1,6 +1,20 @@ +From 077295f6ede59d9e2413b2d19f38cf63b64f4fec Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20Br=C3=BCns?= +Date: Tue, 21 Oct 2025 17:05:59 +0300 +Subject: [PATCH] Do not try to copy pybind11_abseil status extension module + +The module is already installed in the correct location. And even if not, +it should be done as part of the pybind11_abseil build ... +--- + cmake/python.cmake | 5 ----- + ortools/python/setup.py.in | 4 ---- + 2 files changed, 9 deletions(-) + +diff --git a/cmake/python.cmake b/cmake/python.cmake +index 2112ceeb66..db15434303 100644 --- a/cmake/python.cmake +++ b/cmake/python.cmake -@@ -322,7 +322,6 @@ +@@ -326,7 +326,6 @@ file(GENERATE OUTPUT ${PYTHON_PROJECT_DIR}/init/python/__init__.py CONTENT "") file(GENERATE OUTPUT ${PYTHON_PROJECT_DIR}/linear_solver/__init__.py CONTENT "") file(GENERATE OUTPUT ${PYTHON_PROJECT_DIR}/linear_solver/python/__init__.py CONTENT "") if(BUILD_MATH_OPT) @@ -8,17 +22,17 @@ file(GENERATE OUTPUT ${PYTHON_PROJECT_DIR}/math_opt/__init__.py CONTENT "") file(GENERATE OUTPUT ${PYTHON_PROJECT_DIR}/math_opt/core/__init__.py CONTENT "") file(GENERATE OUTPUT ${PYTHON_PROJECT_DIR}/math_opt/core/python/__init__.py CONTENT "") -@@ -635,9 +634,6 @@ +@@ -680,9 +679,6 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E $,copy,true> - $ ${PYTHON_PROJECT}/math_opt/core/python + $ ${PYTHON_PROJECT}/math_opt/io/python - COMMAND ${CMAKE_COMMAND} -E - $,copy,true> - $ ${PYTHON_PROJECT}/../pybind11_abseil COMMAND ${CMAKE_COMMAND} -E $,copy,true> $<$:$> ${PYTHON_PROJECT}/pdlp/python -@@ -696,7 +692,6 @@ +@@ -744,7 +740,6 @@ add_custom_command( COMMAND ${stubgen_EXECUTABLE} -p ortools.constraint_solver.pywrapcp --output . COMMAND ${stubgen_EXECUTABLE} -p ortools.linear_solver.pywraplp --output . COMMAND ${stubgen_EXECUTABLE} -p ortools.linear_solver.python.model_builder_helper --output . @@ -26,9 +40,11 @@ COMMAND ${stubgen_EXECUTABLE} -p ortools.math_opt.core.python.solver --output . COMMAND ${stubgen_EXECUTABLE} -p ortools.pdlp.python.pdlp --output . COMMAND ${stubgen_EXECUTABLE} -p ortools.sat.python.cp_model_helper --output . +diff --git a/ortools/python/setup.py.in b/ortools/python/setup.py.in +index 0aeaa900ef..ae4fa07815 100644 --- a/ortools/python/setup.py.in +++ b/ortools/python/setup.py.in -@@ -83,10 +83,6 @@ +@@ -83,10 +83,6 @@ setup( '*.pyi', 'py.typed' ], @@ -37,5 +53,8 @@ - '*.pyi' - ], '@PYTHON_PROJECT@.math_opt':['*.pyi'], + '@PYTHON_PROJECT@.math_opt.python':['*.pyi'], '@PYTHON_PROJECT@.math_opt.core.python':[ - '$', +-- +2.51.0 + diff --git a/pkgs/by-name/or/or-tools/0001-Fix-up-broken-CMake-rules-for-bundled-pybind-stuff.patch b/pkgs/by-name/or/or-tools/0001-Fix-up-broken-CMake-rules-for-bundled-pybind-stuff.patch new file mode 100644 index 000000000000..568740bd32fd --- /dev/null +++ b/pkgs/by-name/or/or-tools/0001-Fix-up-broken-CMake-rules-for-bundled-pybind-stuff.patch @@ -0,0 +1,26 @@ +From 46e7d2cccd029a2c4215ce9b0c3bf72b2f2dd398 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20Br=C3=BCns?= +Date: Thu, 2 Jan 2025 16:32:05 +0100 +Subject: [PATCH] Fix up broken CMake rules for bundled pybind stuff + +Unfortunately, upstream only uses and tests the bundled code, and the +unbundled cases are bitrotting. +--- + cmake/system_deps.cmake | 1 + + 1 files changed, 1 insertion(+) + +diff --git a/cmake/system_deps.cmake b/cmake/system_deps.cmake +index d9ae923..0c176a8 100644 +--- a/cmake/system_deps.cmake ++++ b/cmake/system_deps.cmake +@@ -94,6 +94,7 @@ endif() + + # Check language Dependencies + if(BUILD_PYTHON) ++ find_package(Python REQUIRED Interpreter Development.Module) + if(NOT BUILD_pybind11 AND NOT TARGET pybind11::pybind11_headers) + find_package(pybind11 REQUIRED) + endif() +-- +2.47.1 + diff --git a/pkgs/development/python-modules/pybind11-protobuf/add-install-target-for-cmake-builds.patch b/pkgs/by-name/or/or-tools/add-install-target-for-cmake-builds.patch similarity index 100% rename from pkgs/development/python-modules/pybind11-protobuf/add-install-target-for-cmake-builds.patch rename to pkgs/by-name/or/or-tools/add-install-target-for-cmake-builds.patch diff --git a/pkgs/by-name/or/or-tools/package.nix b/pkgs/by-name/or/or-tools/package.nix index c8e9ba327ff1..5b068ab449fb 100644 --- a/pkgs/by-name/or/or-tools/package.nix +++ b/pkgs/by-name/or/or-tools/package.nix @@ -1,5 +1,9 @@ { - abseil-cpp_202407, + stdenv, + lib, + callPackage, + + abseil-cpp_202505, bzip2, cbc, cmake, @@ -11,12 +15,10 @@ gbenchmark, glpk, highs, - lib, pkg-config, - protobuf_29, + protobuf_31, python3, re2, - stdenv, swig, unzip, zlib, @@ -30,14 +32,50 @@ let # protobuf. Do not un-pin these, even if you're upgrading them to # what might happen to be the latest version at the current moment; # future upgrades *will* break the build. - abseil-cpp = abseil-cpp_202407; - protobuf = protobuf_29.override { inherit abseil-cpp; }; - python-protobuf = python3.pkgs.protobuf5.override { inherit protobuf; }; - pybind11-protobuf = python3.pkgs.pybind11-protobuf.override { protobuf_29 = protobuf; }; + abseil-cpp' = abseil-cpp_202505; + protobuf' = protobuf_31.override { abseil-cpp = abseil-cpp'; }; + python-protobuf' = python3.pkgs.protobuf5.override { protobuf = protobuf'; }; + + pybind11' = callPackage ./pybind11-2.13.6.nix { + inherit (python3.pkgs) + buildPythonPackage + cmake + ninja + numpy + pytestCheckHook + pythonOlder + setuptools + ; + python = python3; + }; + pybind11-abseil' = python3.pkgs.pybind11-abseil.override { + pybind11 = pybind11'; + abseil-cpp = abseil-cpp'; + }; + pybind11-protobuf' = callPackage ./pybind11-protobuf.nix { + inherit (python3.pkgs) buildPythonPackage; + pybind11 = pybind11'; + }; + # re2 must also use the same abseil version, else these two versions will conflict during linking + re2' = re2.override { abseil-cpp = abseil-cpp'; }; + + # 77a28070b9c4c83995ac6bbfa9544722ff3342ce renamed the scip cmake target(s) differently + # to what upstream still calls it. Apply this patch to scipopt-scip. + scipopt-scip' = scipopt-scip.overrideAttrs (old: { + patches = old.patches or [ ] ++ [ + # from https://github.com/google/or-tools/commit/77a28070b9c4c83995ac6bbfa9544722ff3342ce#diff-c95174a817e73db366d414af1e329c1856f70e5158ed3994d43da88765ccc98f + ./scip.patch + ]; + # Their patch forgets to find_package() soplex, bring it back. + postPatch = (old.postPatch or "") + '' + substituteInPlace CMakeLists.txt \ + --replace-fail 'message(STATUS "Finding Soplex...")' 'find_package(SOPLEX CONFIG HINTS ''${SOPLEX_DIR})' + ''; + }); # local revert of 58daf511687f191829238fc7f571e08dc9dedf56, # working around https://github.com/google/or-tools/issues/4911 - _highs = highs.overrideAttrs (old: rec { + highs' = highs.overrideAttrs (old: rec { version = "1.10.0"; src = fetchFromGitHub { owner = "ERGO-Code"; @@ -57,13 +95,13 @@ let in stdenv.mkDerivation (finalAttrs: { pname = "or-tools"; - version = "9.12"; + version = "9.14"; src = fetchFromGitHub { owner = "google"; repo = "or-tools"; tag = "v${finalAttrs.version}"; - hash = "sha256-5rFeAK51+BfjIyu/5f5ptaKMD7Hd20yHa2Vj3O3PkLU="; + hash = "sha256-FxKe3uY4L33mavwC2aanji3fY9dPqpkwVqi6PNjovSA="; }; patches = [ @@ -74,16 +112,18 @@ stdenv.mkDerivation (finalAttrs: { url = "https://build.opensuse.org/public/source/science/google-or-tools/0001-Revert-python-Fix-python-install-on-windows-breaks-L.patch?rev=19"; hash = "sha256-BNB3KlgjpWcZtb9e68Jkc/4xC4K0c+Iisw0eS6ltYXE="; }) - (fetchpatch { - name = "0001-Fix-up-broken-CMake-rules-for-bundled-pybind-stuff.patch"; - url = "https://build.opensuse.org/public/source/science/google-or-tools/0001-Fix-up-broken-CMake-rules-for-bundled-pybind-stuff.patch?rev=19"; - hash = "sha256-r38ZbRkEW1ZvJb0Uf56c0+HcnfouZZJeEYlIK7quSjQ="; - }) + ./0001-Fix-up-broken-CMake-rules-for-bundled-pybind-stuff.patch (fetchpatch { name = "math_opt-only-run-SCIP-tests-if-enabled.patch"; url = "https://github.com/google/or-tools/commit/b5a2f8ac40dd4bfa4359c35570733171454ec72b.patch"; hash = "sha256-h96zJkqTtwfBd+m7Lm9r/ks/n8uvY4iSPgxMZe8vtXI="; }) + # Fix tests on aarch64-linux + # https://github.com/google/or-tools/issues/4746 + (fetchpatch { + url = "https://github.com/google/or-tools/commit/8442c7b1c219b0c8d58ee96d266d81b7c3a19ad2.patch"; + hash = "sha256-HrV9wU3PFMdb3feGt8i5UJNgHuitMRBF9cNrH5RRENQ="; + }) ]; # or-tools normally attempts to build Protobuf for the build platform when @@ -108,6 +148,8 @@ stdenv.mkDerivation (finalAttrs: { (lib.cmakeFeature "CMAKE_INSTALL_INCLUDEDIR" "include") (lib.cmakeFeature "CMAKE_INSTALL_LIBDIR" "lib") (lib.cmakeBool "FETCH_PYTHON_DEPS" false) + # not packaged in nixpkgs + (lib.cmakeBool "USE_fuzztest" false) (lib.cmakeBool "USE_GLPK" true) (lib.cmakeBool "USE_SCIP" withScip) (lib.cmakeFeature "Python3_EXECUTABLE" "${python3.pythonOnBuildForHost.interpreter}") @@ -136,37 +178,37 @@ stdenv.mkDerivation (finalAttrs: { mypy ]); buildInputs = [ - abseil-cpp + abseil-cpp' bzip2 cbc eigen glpk gbenchmark gtest - _highs + highs' python3.pkgs.absl-py - python3.pkgs.pybind11 - python3.pkgs.pybind11-abseil - pybind11-protobuf + pybind11' + pybind11-abseil' + pybind11-protobuf' python3.pkgs.pytest python3.pkgs.scipy python3.pkgs.setuptools python3.pkgs.wheel - re2 + re2' zlib ]; propagatedBuildInputs = [ - abseil-cpp - _highs - protobuf - python-protobuf + abseil-cpp' + highs' + protobuf' + python-protobuf' python3.pkgs.immutabledict python3.pkgs.numpy python3.pkgs.pandas ] ++ lib.optionals withScip [ # Needed for downstream cmake consumers to not need to set SCIP_ROOT explicitly - scipopt-scip + scipopt-scip' ]; nativeCheckInputs = [ @@ -178,8 +220,8 @@ stdenv.mkDerivation (finalAttrs: { python3.pkgs.virtualenv ]; - # some tests fail on aarch64-linux and hang on darwin - doCheck = stdenv.hostPlatform.isx86_64 && stdenv.hostPlatform.isLinux; + # some tests hang on darwin + doCheck = stdenv.hostPlatform.isLinux; preCheck = '' export LD_LIBRARY_PATH=$LD_LIBRARY_PATH''${LD_LIBRARY_PATH:+:}$PWD/lib diff --git a/pkgs/by-name/or/or-tools/pybind11-2.13.6.nix b/pkgs/by-name/or/or-tools/pybind11-2.13.6.nix new file mode 100644 index 000000000000..048ed89f5632 --- /dev/null +++ b/pkgs/by-name/or/or-tools/pybind11-2.13.6.nix @@ -0,0 +1,131 @@ +# This is pybind11 2.13.6 from an earlier nixpkgs version, with the +# parts from https://github.com/google/or-tools/commit/7f29b27840436e19b6530d5c7f23eeadd819bd3e +# applied. +{ + stdenv, + lib, + buildPythonPackage, + pythonOlder, + fetchFromGitHub, + cmake, + ninja, + setuptools, + boost, + eigen, + python, + catch2, + numpy, + pytestCheckHook, + libxcrypt, + makeSetupHook, +}: +let + setupHook = makeSetupHook { + name = "pybind11-setup-hook"; + substitutions = { + out = placeholder "out"; + pythonInterpreter = python.pythonOnBuildForHost.interpreter; + pythonIncludeDir = "${python}/include/python${python.pythonVersion}"; + pythonSitePackages = "${python}/${python.sitePackages}"; + }; + } ./pybind11-setup-hook.sh; +in +buildPythonPackage rec { + pname = "pybind11"; + version = "2.13.6"; + pyproject = true; + + src = fetchFromGitHub { + owner = "pybind"; + repo = "pybind11"; + tag = "v${version}"; + hash = "sha256-SNLdtrOjaC3lGHN9MAqTf51U9EzNKQLyTMNPe0GcdrU="; + }; + + # https://github.com/google/or-tools/commit/7f29b27840436e19b6530d5c7f23eeadd819bd3e + patches = [ ./pybind11.patch ]; + + build-system = [ + cmake + ninja + setuptools + ]; + + buildInputs = lib.optionals (pythonOlder "3.9") [ libxcrypt ]; + propagatedNativeBuildInputs = [ setupHook ]; + + dontUseCmakeBuildDir = true; + + # Don't build tests if not needed, read the doInstallCheck value at runtime + preConfigure = '' + if [ -n "$doInstallCheck" ]; then + cmakeFlagsArray+=("-DBUILD_TESTING=ON") + fi + ''; + + cmakeFlags = [ + "-DBoost_INCLUDE_DIR=${lib.getDev boost}/include" + "-DCATCH_INCLUDE_DIR=${lib.getDev catch2}/include/catch2" + "-DEIGEN3_INCLUDE_DIR=${lib.getDev eigen}/include/eigen3" + ] + ++ lib.optionals (python.isPy3k && !stdenv.cc.isClang) [ "-DPYBIND11_CXX_STANDARD=-std=c++17" ]; + + postBuild = '' + # build tests + make -j $NIX_BUILD_CORES + ''; + + postInstall = '' + make install + # Symlink the CMake-installed headers to the location expected by setuptools + mkdir -p $out/include/${python.libPrefix} + ln -sf $out/include/pybind11 $out/include/${python.libPrefix}/pybind11 + ''; + + nativeCheckInputs = [ + catch2 + numpy + pytestCheckHook + ]; + + disabledTestPaths = [ + # require dependencies not available in nixpkgs + "tests/test_embed/test_trampoline.py" + "tests/test_embed/test_interpreter.py" + # numpy changed __repr__ output of numpy dtypes + "tests/test_numpy_dtypes.py" + # no need to test internal packaging + "tests/extra_python_package/test_files.py" + # tests that try to parse setuptools stdout + "tests/extra_setuptools/test_setuphelper.py" + ]; + + disabledTests = lib.optionals stdenv.hostPlatform.isDarwin [ + # expects KeyError, gets RuntimeError + # https://github.com/pybind/pybind11/issues/4243 + "test_cross_module_exception_translator" + ]; + + postCheck = '' + make cpptest + ''; + + hardeningDisable = lib.optional stdenv.hostPlatform.isMusl "fortify"; + + meta = { + homepage = "https://github.com/pybind/pybind11"; + changelog = "https://github.com/pybind/pybind11/blob/${src.rev}/docs/changelog.rst"; + description = "Seamless operability between C++11 and Python"; + mainProgram = "pybind11-config"; + longDescription = '' + Pybind11 is a lightweight header-only library that exposes + C++ types in Python and vice versa, mainly to create Python + bindings of existing C++ code. + ''; + license = lib.licenses.bsd3; + maintainers = with lib.maintainers; [ + yuriaisaka + dotlambda + ]; + }; +} diff --git a/pkgs/development/python-modules/pybind11-protobuf/default.nix b/pkgs/by-name/or/or-tools/pybind11-protobuf.nix similarity index 78% rename from pkgs/development/python-modules/pybind11-protobuf/default.nix rename to pkgs/by-name/or/or-tools/pybind11-protobuf.nix index eb7c0aa0b072..a93268e9358d 100644 --- a/pkgs/development/python-modules/pybind11-protobuf/default.nix +++ b/pkgs/by-name/or/or-tools/pybind11-protobuf.nix @@ -4,22 +4,22 @@ buildPythonPackage, fetchFromGitHub, cmake, - abseil-cpp_202407, # downgrade, same reason as toplevel protobuf_29 - protobuf_29, + abseil-cpp_202505, + protobuf, pybind11, zlib, }: buildPythonPackage { pname = "pybind11-protobuf"; - version = "0-unstable-2025-02-10"; + version = "0-unstable-2025-10-29"; pyproject = false; src = fetchFromGitHub { owner = "pybind"; repo = "pybind11_protobuf"; - rev = "f02a2b7653bc50eb5119d125842a3870db95d251"; - hash = "sha256-jlZcxQKYYYvTOGhk+0Sgtek4oKy6R1wDGiBOf2t+KiU="; + rev = "4825dca68c8de73f5655fc50ce79c49c4d814652"; + hash = "sha256-SeIUyWLeThfBX3SljLdG7CbENdbuJG+X0+h/gn/ATWE="; }; patches = [ @@ -28,11 +28,16 @@ buildPythonPackage { ./add-install-target-for-cmake-builds.patch ]; + postPatch = '' + substituteInPlace cmake/dependencies/CMakeLists.txt \ + --replace-fail 'find_package(protobuf 5.29.2 REQUIRED)' 'find_package(protobuf REQUIRED)' + ''; + nativeBuildInputs = [ cmake ]; buildInputs = [ - abseil-cpp_202407 - protobuf_29 + abseil-cpp_202505 + protobuf pybind11 zlib ]; diff --git a/pkgs/by-name/or/or-tools/pybind11-setup-hook.sh b/pkgs/by-name/or/or-tools/pybind11-setup-hook.sh new file mode 100644 index 000000000000..a86eed36f1ec --- /dev/null +++ b/pkgs/by-name/or/or-tools/pybind11-setup-hook.sh @@ -0,0 +1,12 @@ +# Tell the pybind11 CMake module where to find host platform Python. This is +# required when cross-compiling. +pybind11CMakeFlags () { + cmakeFlagsArray+=( + '-DPYBIND11_PYTHONLIBS_OVERWRITE=OFF' + '-DPYTHON_EXECUTABLE=@pythonInterpreter@' + '-DPYTHON_INCLUDE_DIR=@pythonIncludeDir@' + '-DPYTHON_SITE_PACKAGES=@pythonSitePackages@' + ) +} + +preConfigureHooks+=(pybind11CMakeFlags) diff --git a/pkgs/by-name/or/or-tools/pybind11.patch b/pkgs/by-name/or/or-tools/pybind11.patch new file mode 100644 index 000000000000..190e8471c467 --- /dev/null +++ b/pkgs/by-name/or/or-tools/pybind11.patch @@ -0,0 +1,452 @@ +diff --git a/include/pybind11/stl.h b/include/pybind11/stl.h +index 71bc5902..6a148e74 100644 +--- a/include/pybind11/stl.h ++++ b/include/pybind11/stl.h +@@ -11,10 +11,14 @@ + + #include "pybind11.h" + #include "detail/common.h" ++#include "detail/descr.h" ++#include "detail/type_caster_base.h" + + #include ++#include + #include + #include ++#include + #include + #include + #include +@@ -35,6 +39,89 @@ + PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) + PYBIND11_NAMESPACE_BEGIN(detail) + ++// ++// Begin: Equivalent of ++// https://github.com/google/clif/blob/ae4eee1de07cdf115c0c9bf9fec9ff28efce6f6c/clif/python/runtime.cc#L388-L438 ++/* ++The three `PyObjectTypeIsConvertibleTo*()` functions below are ++the result of converging the behaviors of pybind11 and PyCLIF ++(http://github.com/google/clif). ++ ++Originally PyCLIF was extremely far on the permissive side of the spectrum, ++while pybind11 was very far on the strict side. Originally PyCLIF accepted any ++Python iterable as input for a C++ `vector`/`set`/`map` argument, as long as ++the elements were convertible. The obvious (in hindsight) problem was that ++any empty Python iterable could be passed to any of these C++ types, e.g. `{}` ++was accepted for C++ `vector`/`set` arguments, or `[]` for C++ `map` arguments. ++ ++The functions below strike a practical permissive-vs-strict compromise, ++informed by tens of thousands of use cases in the wild. A main objective is ++to prevent accidents and improve readability: ++ ++- Python literals must match the C++ types. ++ ++- For C++ `set`: The potentially reducing conversion from a Python sequence ++ (e.g. Python `list` or `tuple`) to a C++ `set` must be explicit, by going ++ through a Python `set`. ++ ++- However, a Python `set` can still be passed to a C++ `vector`. The rationale ++ is that this conversion is not reducing. Implicit conversions of this kind ++ are also fairly commonly used, therefore enforcing explicit conversions ++ would have an unfavorable cost : benefit ratio; more sloppily speaking, ++ such an enforcement would be more annoying than helpful. ++*/ ++ ++inline bool PyObjectIsInstanceWithOneOfTpNames(PyObject *obj, ++ std::initializer_list tp_names) { ++ if (PyType_Check(obj)) { ++ return false; ++ } ++ const char *obj_tp_name = Py_TYPE(obj)->tp_name; ++ for (const auto *tp_name : tp_names) { ++ if (std::strcmp(obj_tp_name, tp_name) == 0) { ++ return true; ++ } ++ } ++ return false; ++} ++ ++inline bool PyObjectTypeIsConvertibleToStdVector(PyObject *obj) { ++ if (PySequence_Check(obj) != 0) { ++ return !PyUnicode_Check(obj) && !PyBytes_Check(obj); ++ } ++ return (PyGen_Check(obj) != 0) || (PyAnySet_Check(obj) != 0) ++ || PyObjectIsInstanceWithOneOfTpNames( ++ obj, {"dict_keys", "dict_values", "dict_items", "map", "zip"}); ++} ++ ++inline bool PyObjectTypeIsConvertibleToStdSet(PyObject *obj) { ++ return (PyAnySet_Check(obj) != 0) || PyObjectIsInstanceWithOneOfTpNames(obj, {"dict_keys"}); ++} ++ ++inline bool PyObjectTypeIsConvertibleToStdMap(PyObject *obj) { ++ if (PyDict_Check(obj)) { ++ return true; ++ } ++ // Implicit requirement in the conditions below: ++ // A type with `.__getitem__()` & `.items()` methods must implement these ++ // to be compatible with https://docs.python.org/3/c-api/mapping.html ++ if (PyMapping_Check(obj) == 0) { ++ return false; ++ } ++ PyObject *items = PyObject_GetAttrString(obj, "items"); ++ if (items == nullptr) { ++ PyErr_Clear(); ++ return false; ++ } ++ bool is_convertible = (PyCallable_Check(items) != 0); ++ Py_DECREF(items); ++ return is_convertible; ++} ++ ++// ++// End: Equivalent of clif/python/runtime.cc ++// ++ + /// Extracts an const lvalue reference or rvalue reference for U based on the type of T (e.g. for + /// forwarding a container element). Typically used indirect via forwarded_type(), below. + template +@@ -66,17 +153,10 @@ private: + } + void reserve_maybe(const anyset &, void *) {} + +-public: +- bool load(handle src, bool convert) { +- if (!isinstance(src)) { +- return false; +- } +- auto s = reinterpret_borrow(src); +- value.clear(); +- reserve_maybe(s, &value); +- for (auto entry : s) { ++ bool convert_iterable(const iterable &itbl, bool convert) { ++ for (const auto &it : itbl) { + key_conv conv; +- if (!conv.load(entry, convert)) { ++ if (!conv.load(it, convert)) { + return false; + } + value.insert(cast_op(std::move(conv))); +@@ -84,6 +164,29 @@ public: + return true; + } + ++ bool convert_anyset(anyset s, bool convert) { ++ value.clear(); ++ reserve_maybe(s, &value); ++ return convert_iterable(s, convert); ++ } ++ ++public: ++ bool load(handle src, bool convert) { ++ if (!PyObjectTypeIsConvertibleToStdSet(src.ptr())) { ++ return false; ++ } ++ if (isinstance(src)) { ++ value.clear(); ++ return convert_anyset(reinterpret_borrow(src), convert); ++ } ++ if (!convert) { ++ return false; ++ } ++ assert(isinstance(src)); ++ value.clear(); ++ return convert_iterable(reinterpret_borrow(src), convert); ++ } ++ + template + static handle cast(T &&src, return_value_policy policy, handle parent) { + if (!std::is_lvalue_reference::value) { +@@ -115,15 +218,10 @@ private: + } + void reserve_maybe(const dict &, void *) {} + +-public: +- bool load(handle src, bool convert) { +- if (!isinstance(src)) { +- return false; +- } +- auto d = reinterpret_borrow(src); ++ bool convert_elements(const dict &d, bool convert) { + value.clear(); + reserve_maybe(d, &value); +- for (auto it : d) { ++ for (const auto &it : d) { + key_conv kconv; + value_conv vconv; + if (!kconv.load(it.first.ptr(), convert) || !vconv.load(it.second.ptr(), convert)) { +@@ -134,6 +232,25 @@ public: + return true; + } + ++public: ++ bool load(handle src, bool convert) { ++ if (!PyObjectTypeIsConvertibleToStdMap(src.ptr())) { ++ return false; ++ } ++ if (isinstance(src)) { ++ return convert_elements(reinterpret_borrow(src), convert); ++ } ++ if (!convert) { ++ return false; ++ } ++ auto items = reinterpret_steal(PyMapping_Items(src.ptr())); ++ if (!items) { ++ throw error_already_set(); ++ } ++ assert(isinstance(items)); ++ return convert_elements(dict(reinterpret_borrow(items)), convert); ++ } ++ + template + static handle cast(T &&src, return_value_policy policy, handle parent) { + dict d; +@@ -166,13 +283,35 @@ struct list_caster { + using value_conv = make_caster; + + bool load(handle src, bool convert) { +- if (!isinstance(src) || isinstance(src) || isinstance(src)) { ++ if (!PyObjectTypeIsConvertibleToStdVector(src.ptr())) { + return false; + } +- auto s = reinterpret_borrow(src); ++ if (isinstance(src)) { ++ return convert_elements(src, convert); ++ } ++ if (!convert) { ++ return false; ++ } ++ // Designed to be behavior-equivalent to passing tuple(src) from Python: ++ // The conversion to a tuple will first exhaust the generator object, to ensure that ++ // the generator is not left in an unpredictable (to the caller) partially-consumed ++ // state. ++ assert(isinstance(src)); ++ return convert_elements(tuple(reinterpret_borrow(src)), convert); ++ } ++ ++private: ++ template ::value, int> = 0> ++ void reserve_maybe(const sequence &s, Type *) { ++ value.reserve(s.size()); ++ } ++ void reserve_maybe(const sequence &, void *) {} ++ ++ bool convert_elements(handle seq, bool convert) { ++ auto s = reinterpret_borrow(seq); + value.clear(); + reserve_maybe(s, &value); +- for (const auto &it : s) { ++ for (const auto &it : seq) { + value_conv conv; + if (!conv.load(it, convert)) { + return false; +@@ -182,13 +321,6 @@ struct list_caster { + return true; + } + +-private: +- template ::value, int> = 0> +- void reserve_maybe(const sequence &s, Type *) { +- value.reserve(s.size()); +- } +- void reserve_maybe(const sequence &, void *) {} +- + public: + template + static handle cast(T &&src, return_value_policy policy, handle parent) { +@@ -220,43 +352,87 @@ struct type_caster> : list_caster + struct type_caster> : list_caster, Type> {}; + ++template ++ArrayType vector_to_array_impl(V &&v, index_sequence) { ++ return {{std::move(v[I])...}}; ++} ++ ++// Based on https://en.cppreference.com/w/cpp/container/array/to_array ++template ++ArrayType vector_to_array(V &&v) { ++ return vector_to_array_impl(std::forward(v), make_index_sequence{}); ++} ++ + template + struct array_caster { + using value_conv = make_caster; + + private: +- template +- bool require_size(enable_if_t size) { +- if (value.size() != size) { +- value.resize(size); ++ std::unique_ptr value; ++ ++ template = 0> ++ bool convert_elements(handle seq, bool convert) { ++ auto l = reinterpret_borrow(seq); ++ value.reset(new ArrayType{}); ++ // Using `resize` to preserve the behavior exactly as it was before PR #5305 ++ // For the `resize` to work, `Value` must be default constructible. ++ // For `std::valarray`, this is a requirement: ++ // https://en.cppreference.com/w/cpp/named_req/NumericType ++ value->resize(l.size()); ++ size_t ctr = 0; ++ for (const auto &it : l) { ++ value_conv conv; ++ if (!conv.load(it, convert)) { ++ return false; ++ } ++ (*value)[ctr++] = cast_op(std::move(conv)); + } + return true; + } +- template +- bool require_size(enable_if_t size) { +- return size == Size; +- } + +-public: +- bool load(handle src, bool convert) { +- if (!isinstance(src)) { ++ template = 0> ++ bool convert_elements(handle seq, bool convert) { ++ auto l = reinterpret_borrow(seq); ++ if (l.size() != Size) { + return false; + } +- auto l = reinterpret_borrow(src); +- if (!require_size(l.size())) { +- return false; +- } +- size_t ctr = 0; +- for (const auto &it : l) { ++ // The `temp` storage is needed to support `Value` types that are not ++ // default-constructible. ++ // Deliberate choice: no template specializations, for simplicity, and ++ // because the compile time overhead for the specializations is deemed ++ // more significant than the runtime overhead for the `temp` storage. ++ std::vector temp; ++ temp.reserve(l.size()); ++ for (auto it : l) { + value_conv conv; + if (!conv.load(it, convert)) { + return false; + } +- value[ctr++] = cast_op(std::move(conv)); ++ temp.emplace_back(cast_op(std::move(conv))); + } ++ value.reset(new ArrayType(vector_to_array(std::move(temp)))); + return true; + } + ++public: ++ bool load(handle src, bool convert) { ++ if (!PyObjectTypeIsConvertibleToStdVector(src.ptr())) { ++ return false; ++ } ++ if (isinstance(src)) { ++ return convert_elements(src, convert); ++ } ++ if (!convert) { ++ return false; ++ } ++ // Designed to be behavior-equivalent to passing tuple(src) from Python: ++ // The conversion to a tuple will first exhaust the generator object, to ensure that ++ // the generator is not left in an unpredictable (to the caller) partially-consumed ++ // state. ++ assert(isinstance(src)); ++ return convert_elements(tuple(reinterpret_borrow(src)), convert); ++ } ++ + template + static handle cast(T &&src, return_value_policy policy, handle parent) { + list l(src.size()); +@@ -272,12 +448,36 @@ public: + return l.release(); + } + +- PYBIND11_TYPE_CASTER(ArrayType, +- const_name(const_name(""), const_name("Annotated[")) +- + const_name("list[") + value_conv::name + const_name("]") +- + const_name(const_name(""), +- const_name(", FixedSize(") +- + const_name() + const_name(")]"))); ++ // Code copied from PYBIND11_TYPE_CASTER macro. ++ // Intentionally preserving the behavior exactly as it was before PR #5305 ++ template >::value, int> = 0> ++ static handle cast(T_ *src, return_value_policy policy, handle parent) { ++ if (!src) { ++ return none().release(); ++ } ++ if (policy == return_value_policy::take_ownership) { ++ auto h = cast(std::move(*src), policy, parent); ++ delete src; // WARNING: Assumes `src` was allocated with `new`. ++ return h; ++ } ++ return cast(*src, policy, parent); ++ } ++ ++ // NOLINTNEXTLINE(google-explicit-constructor) ++ operator ArrayType *() { return &(*value); } ++ // NOLINTNEXTLINE(google-explicit-constructor) ++ operator ArrayType &() { return *value; } ++ // NOLINTNEXTLINE(google-explicit-constructor) ++ operator ArrayType &&() && { return std::move(*value); } ++ ++ template ++ using cast_op_type = movable_cast_op_type; ++ ++ static constexpr auto name ++ = const_name(const_name(""), const_name("Annotated[")) + const_name("list[") ++ + value_conv::name + const_name("]") ++ + const_name( ++ const_name(""), const_name(", FixedSize(") + const_name() + const_name(")]")); + }; + + template +diff --git a/tests/test_stl.cpp b/tests/test_stl.cpp +index e7db8aaa..84bd4755 100644 +--- a/tests/test_stl.cpp ++++ b/tests/test_stl.cpp +@@ -193,6 +193,23 @@ TEST_SUBMODULE(stl, m) { + m.def("cast_array", []() { return std::array{{1, 2}}; }); + m.def("load_array", [](const std::array &a) { return a[0] == 1 && a[1] == 2; }); + ++ struct NoDefaultCtor { ++ explicit constexpr NoDefaultCtor(int val) : val{val} {} ++ int val; ++ }; ++ ++ struct NoDefaultCtorArray { ++ explicit constexpr NoDefaultCtorArray(int i) ++ : arr{{NoDefaultCtor(10 + i), NoDefaultCtor(20 + i)}} {} ++ std::array arr; ++ }; ++ ++ // test_array_no_default_ctor ++ py::class_(m, "NoDefaultCtor").def_readonly("val", &NoDefaultCtor::val); ++ py::class_(m, "NoDefaultCtorArray") ++ .def(py::init()) ++ .def_readwrite("arr", &NoDefaultCtorArray::arr); ++ + // test_valarray + m.def("cast_valarray", []() { return std::valarray{1, 4, 9}; }); + m.def("load_valarray", [](const std::valarray &v) { +diff --git a/tests/test_stl.py b/tests/test_stl.py +index 65fda54c..340cdc35 100644 +--- a/tests/test_stl.py ++++ b/tests/test_stl.py +@@ -48,6 +48,13 @@ def test_array(doc): + ) + + ++def test_array_no_default_ctor(): ++ lst = m.NoDefaultCtorArray(3) ++ assert [e.val for e in lst.arr] == [13, 23] ++ lst.arr = m.NoDefaultCtorArray(4).arr ++ assert [e.val for e in lst.arr] == [14, 24] ++ ++ + def test_valarray(doc): + """std::valarray <-> list""" + lst = m.cast_valarray() diff --git a/pkgs/by-name/or/or-tools/scip.patch b/pkgs/by-name/or/or-tools/scip.patch new file mode 100644 index 000000000000..7a92254118b6 --- /dev/null +++ b/pkgs/by-name/or/or-tools/scip.patch @@ -0,0 +1,145 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 8492dc75..4c12a9bf 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -38,9 +38,11 @@ set(CPACK_PACKAGE_VENDOR "Zuse Institute Berlin") + set(CPACK_PACKAGE_CONTACT "http://scipopt.org") + include(CPack) + +-set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) +-set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) +-set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) ++if(CMAKE_PROJECT_NAME EQUAL "SCIP") ++ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) ++ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) ++ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) ++endif() + + if(SCIPOptSuite_BINARY_DIR) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${SCIPOptSuite_BINARY_DIR}/bin) +@@ -412,22 +414,11 @@ endif() + #search the selected LP solver library + message(STATUS "Finding Solver \"${LPS}\"") + if(LPS STREQUAL "spx") +- message(STATUS "Finding Soplex") +- find_package(SOPLEX CONFIG HINTS ${SOPLEX_DIR}) +- if(NOT SOPLEX_FOUND) +- # Utilities to automatically download missing dependencies +- include(cmake/Dependencies.cmake) +- find_or_download_package( +- NAME SOPLEX +- VERSION 7.0.1 +- URL https://github.com/scipopt/soplex/archive/refs/tags/release-701.tar.gz +- URL_HASH SHA256=80cce994dcbe45fd52b60e31a3aeb5d2c60a7ddbaae495e0ce6bf58481675696 +- COMPONENTS soplex) +- find_package(SOPLEX REQUIRED CONFIG HINTS _deps/local) +- endif() +- if(NOT SOPLEX_FOUND) ++ message(STATUS "Finding Soplex...") ++ if(NOT TARGET libsoplex-pic OR NOT TARGET libsoplex) + message(FATAL_ERROR "Requested LP solver SoPlex not found.") + endif() ++ set(SOPLEX_FOUND TRUE) + if (DEFINED SOPLEX_WITH_PAPILO) + message(STATUS "SOPLEX links PAPILO") + if((NOT SCIP_WITH_PAPILO)) # TODO not sure how to handle AUTOBUILD +@@ -502,9 +493,9 @@ if(SOPLEX_FOUND) + message(STATUS "Finding SOPLEX - found") + # SoPlex headers can be directly included + include_directories(${SOPLEX_INCLUDE_DIRS}) +- set(LPS_LIBRARIES ${SOPLEX_LIBRARIES}) ++ set(LPS_LIBRARIES libsoplex) + if(SHARED) +- set(LPS_PIC_LIBRARIES ${SOPLEX_PIC_LIBRARIES}) ++ set(LPS_PIC_LIBRARIES libsoplex-pic) + else() + set(LPS_PIC_LIBRARIES ${LPS_LIBRARIES}) + endif() +@@ -514,7 +505,7 @@ if(SOPLEX_FOUND) + set(lpi lpi/lpi_spx2.cpp) + endif() + else() +- message(STATUS "Support SOPLEX: OFF") ++ message(FATAL_ERROR "SOPLEX not found !") + endif() + + if(CLP_FOUND) +diff --git a/scip-config.cmake.in b/scip-config.cmake.in +index 559552f9..682ac40a 100644 +--- a/scip-config.cmake.in ++++ b/scip-config.cmake.in +@@ -1,17 +1,16 @@ + if(NOT TARGET libscip) +- include("${CMAKE_CURRENT_LIST_DIR}/scip-targets.cmake") +-endif() ++ include(CMakeFindDependencyMacro) ++ if(@ZIMPL_NEEDED@) ++ find_dependency(ZIMPL REQUIRED NO_MODULE) ++ endif() ++ if(@SOPLEX_NEEDED@) ++ find_dependency(SOPLEX REQUIRED NO_MODULE) ++ endif() + +-if(@ZIMPL_NEEDED@) +- set(ZIMPL_DIR "@CONF_ZIMPL_DIR@") +- find_package(ZIMPL QUIET CONFIG) +-endif() +- +-if(@SOPLEX_NEEDED@) +- set(SOPLEX_DIR "@CONF_SOPLEX_DIR@") +- find_package(SOPLEX QUIET CONFIG) ++ include("${CMAKE_CURRENT_LIST_DIR}/scip-targets.cmake") + endif() + ++# Legacy + set(SCIP_LIBRARIES libscip) + set(SCIP_INCLUDE_DIRS "@CONF_INCLUDE_DIRS@") + set(SCIP_FOUND TRUE) +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index e6fda2d5..2d04b845 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -1149,17 +1149,8 @@ install(TARGETS scip libscip EXPORT scip-targets + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + + # Add all targets to the build-tree export set +-export(TARGETS scip libscip +- FILE "${PROJECT_BINARY_DIR}/scip-targets.cmake") +- +-# make soplex and zimpl dir absolute for the config file +-if(SOPLEX_NEEDED) +- get_filename_component(CONF_SOPLEX_DIR ${SOPLEX_DIR} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR}) +-endif() +- +-if(ZIMPL_NEEDED) +- get_filename_component(CONF_ZIMPL_DIR ${ZIMPL_DIR} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR}) +-endif() ++#export(TARGETS scip libscip ++# FILE "${PROJECT_BINARY_DIR}/scip-targets.cmake") + + # configure the config file for the build tree + set(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src" "${PROJECT_BINARY_DIR}") +@@ -1175,18 +1166,16 @@ ${PROJECT_BINARY_DIR}/scip-config-version.cmake + + #configure the config file for the install + set(CONF_INCLUDE_DIRS "\${CMAKE_CURRENT_LIST_DIR}/../../../include") +-if(SOPLEX_NEEDED) +- set(CONF_SOPLEX_DIR "\${CMAKE_CURRENT_LIST_DIR}/../soplex") +-endif() +-if(ZIMPL_NEEDED) +- set(CONF_ZIMPL_DIR "\${CMAKE_CURRENT_LIST_DIR}/../zimpl") +-endif() + configure_file(${PROJECT_SOURCE_DIR}/scip-config.cmake.in + "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/scip-config.cmake" @ONLY) + + # install the targets of the scip export group and the config file so that other projects + # can link easily against scip +-install(EXPORT scip-targets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/scip) ++install(EXPORT scip-targets ++ NAMESPACE SCIP:: ++ DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/scip ++ COMPONENT Devel ++) + install(FILES "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/scip-config.cmake" + ${PROJECT_BINARY_DIR}/scip-config-version.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/scip) diff --git a/pkgs/top-level/aliases.nix b/pkgs/top-level/aliases.nix index 3a0be3791863..0a45c3cb7454 100644 --- a/pkgs/top-level/aliases.nix +++ b/pkgs/top-level/aliases.nix @@ -268,7 +268,6 @@ mapAliases { a4term = throw "'a4term' has been renamed to/replaced by 'a4'"; # Converted to throw 2025-10-27 abseil-cpp_202301 = throw "abseil-cpp_202301 has been removed as it was unused in tree"; # Added 2025-08-09 abseil-cpp_202501 = throw "abseil-cpp_202501 has been removed as it was unused in tree"; # Added 2025-09-15 - abseil-cpp_202505 = throw "abseil-cpp_202505 has been removed as it was unused in tree"; # Added 2025-09-15 adminer-pematon = throw "'adminer-pematon' has been renamed to/replaced by 'adminneo'"; # Converted to throw 2025-10-27 adminerneo = throw "'adminerneo' has been renamed to/replaced by 'adminneo'"; # Converted to throw 2025-10-27 adobe-reader = throw "'adobe-reader' has been removed, as it was broken, outdated and insecure"; # added 2025-05-31 diff --git a/pkgs/top-level/python-aliases.nix b/pkgs/top-level/python-aliases.nix index 09a152461df1..f687ec51ab20 100644 --- a/pkgs/top-level/python-aliases.nix +++ b/pkgs/top-level/python-aliases.nix @@ -310,6 +310,7 @@ mapAliases { py-eth-sig-utils = throw "py-eth-sig-utils has been removed because it has been marked as broken since at least November 2024."; # Added 2025-10-04 py-scrypt = scrypt; # added 2025-08-07 py_stringmatching = throw "'py_stringmatching' has been renamed to/replaced by 'py-stringmatching'"; # Converted to throw 2025-10-29 + pybind11-protobuf = throw "'pybind11-protobuf' was only used by or-tools, and with some overrides, so vendored in there until it's used in other places."; # Converted to throw 2025-11-06 pycategories = throw "'pycategories' has been removed as it was broken and unmaintained"; # added 2025-11-08 PyChromecast = throw "'PyChromecast' has been renamed to/replaced by 'pychromecast'"; # Converted to throw 2025-10-29 pydns = throw "'pydns' has been renamed to/replaced by 'py3dns'"; # Converted to throw 2025-10-29 diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix index 557371ad8fb5..4a3ec8210f12 100644 --- a/pkgs/top-level/python-packages.nix +++ b/pkgs/top-level/python-packages.nix @@ -12774,8 +12774,6 @@ self: super: with self; { pybind11-abseil = callPackage ../development/python-modules/pybind11-abseil { }; - pybind11-protobuf = callPackage ../development/python-modules/pybind11-protobuf { }; - pybind11-stubgen = callPackage ../development/python-modules/pybind11-stubgen { }; pybindgen = callPackage ../development/python-modules/pybindgen { };